質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Unity3D

Unity3Dは、ゲームや対話式の3Dアプリケーション、トレーニングシュミレーション、そして医学的・建築学的な技術を可視化する、商業用の開発プラットフォームです。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

解決済

1回答

526閲覧

Rotationのキーリダクションが正しく行われない

flame_mori

総合スコア12

Unity3D

Unity3Dは、ゲームや対話式の3Dアプリケーション、トレーニングシュミレーション、そして医学的・建築学的な技術を可視化する、商業用の開発プラットフォームです。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

0グッド

0クリップ

投稿2022/08/18 04:41

編集2022/08/19 00:37

前提

アニメーションのキーリダクションを行うスクリプトを作っているのですが、以下のコードでキーリダクションを行うと、Rotationだけ正しく行われません。
正確には、xはうまくいっているのですが、y、zは一部の値が変わってしまっているようです。

キーリダクション前:
イメージ説明

キーリダクション後:
イメージ説明

スクリーンショットで使用したanimファイル

実現したいこと

Rotationのキーリダクションが正しく動作する

該当のソースコード

c#

1using System.IO; 2using System.Linq; 3using UnityEngine; 4using UnityEditor; 5using System.Collections.Generic; 6using System; 7 8public class KeyReductionTest : AssetPostprocessor 9{ 10 [MenuItem("Assets/Key Reduction Test")] 11 static void KeyReduction() 12 { 13 Debug.Log("Key Reduction Test..."); 14 foreach (UnityEngine.Object obj in Selection.GetFiltered(typeof(AnimationClip), SelectionMode.Editable)) 15 { 16 string path = AssetDatabase.GetAssetPath(obj); 17 AnimationClip anim_clip = (AnimationClip)AssetDatabase.LoadAssetAtPath(path, typeof(AnimationClip)); 18 19 foreach (var binding in AnimationUtility.GetCurveBindings(anim_clip).ToArray()) 20 { 21 AnimationCurve curve = AnimationUtility.GetEditorCurve(anim_clip, binding); 22 AnimationCurveKeyReduction(curve, binding.propertyName, 0.001f); 23 AnimationUtility.SetEditorCurve(anim_clip, binding, curve); 24 } 25 string anim_clip_name = Path.GetDirectoryName(path) + "/" + Path.GetFileNameWithoutExtension(path); 26 WriteAnimationCurve(anim_clip, anim_clip_name); 27 } 28 } 29 30 static private void WriteAnimationCurve(AnimationClip anim_clip, string anim_clip_name) 31 { 32 string tmp_name = anim_clip_name + "_tmp.anim"; 33 var copyClip = UnityEngine.Object.Instantiate(anim_clip); 34 AssetDatabase.CreateAsset(copyClip, tmp_name); 35 FileUtil.ReplaceFile(tmp_name, anim_clip_name + ".anim"); 36 AssetDatabase.DeleteAsset(tmp_name); 37 AssetDatabase.Refresh(); 38 } 39 40 static private float GetValueFromTime(Keyframe key1, Keyframe key2, float time) 41 { 42 float t; 43 float a, b, c; 44 float kd, vd; 45 46 if (key1.outTangent == Mathf.Infinity) return key1.value; 47 48 kd = key2.time - key1.time; 49 vd = key2.value - key1.value; 50 t = (time - key1.time) / kd; 51 52 a = -2 * vd + kd * (key1.outTangent + key2.inTangent); 53 b = 3 * vd - kd * (2 * key1.outTangent + key2.inTangent); 54 c = kd * key1.outTangent; 55 56 return key1.value + t * (t * (a * t + b) + c); 57 } 58 59 static private bool IsInterpolationValue(Keyframe key1, Keyframe key2, Keyframe comp, float eps) 60 { 61 var val1 = GetValueFromTime(key1, key2, comp.time); 62 63 if (eps < System.Math.Abs(comp.value - val1)) return false; 64 65 var time = key1.time + (comp.time - key1.time) * 0.5f; 66 val1 = GetValueFromTime(key1, comp, time); 67 var val2 = GetValueFromTime(key1, key2, time); 68 69 return (System.Math.Abs(val2 - val1) <= eps) ? true : false; 70 } 71 72 static public IEnumerable<int> GetDeleteKeyIndex(Keyframe[] keys, float eps) 73 { 74 for (int s_idx = 0, i = 1; i < keys.Length - 1; i++) 75 { 76 if (IsInterpolationValue(keys[s_idx], keys[i + 1], keys[i], eps)) 77 { 78 yield return i; 79 } 80 else 81 { 82 s_idx = i; 83 } 84 } 85 } 86 87 static public void AnimationCurveKeyReduction(AnimationCurve in_curve, string propertyName, float eps = 0.0001f) 88 { 89 if (in_curve.keys.Length <= 2) return; 90 var del_indexes = GetDeleteKeyIndex(in_curve.keys, eps).ToArray(); 91 foreach (var del_idx in del_indexes.Reverse()) in_curve.RemoveKey(del_idx); 92 } 93}

補足情報(FW/ツールのバージョンなど)

Unity 2020.3.19f1

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Bongo

2022/08/18 21:44

Animationビュー上のSpotLightBase_B_y_03 : Rotationを右クリックするとコンテキストメニュー上に「Interpolation」という項目があるかと思いますが、それの設定はどうなっているでしょうかね(https://docs.unity3d.com/ja/2020.3/Manual/animeditor-AnimationCurves.html#:~:text=%E3%81%8C%E3%81%82%E3%82%8A%E3%81%BE%E3%81%99%E3%80%82-,%E5%9B%9E%E8%BB%A2%E3%81%AE%E8%A3%9C%E9%96%93%E6%96%B9%E6%B3%95%E3%81%AE%E7%A8%AE%E9%A1%9E,-Unity%20%E3%81%A7%E3%81%AF%E5%9B%9E%E8%BB%A2 )? あれが「Quaternion」だと、Animationビュー上では回転がオイラー角で表示されていても、内部的にはQuaternion方式でデータが保存されるようです。スクリーンショットを拝見しますにX軸回転90°付近で特にズレが大きくなっているように見えますが、もしかするとQuaternionからAnimationビュー上のオイラー角へ変換する際に起こる致し方ない現象なのかもしれませんね。Animationビュー上の見た目が少々おかしくても、実際にアニメーションを再生したときに不自然な動きがないようでしたらお気になさる必要はないかもしれません。 キーリダクション前のアニメーションクリップファイルをどこかにアップロードしていただくことは可能でしょうか?それがあれば挙動を調べやすくなるんじゃないかと思います。
flame_mori

2022/08/19 00:39

キーリダクション前のアニメーションクリップファイルをアップロードしましたので、本文にリンクを追加しました。 スクリーンショットのすぐ下に追加しています。 「Interpolation」の設定ですが「Quaternion」になっていることを確認しました。
flame_mori

2022/08/19 01:05

「Interpolation」を「Euler Angles」に変更してキーリダクションを行ったところ、正しく動くことを確認できました。 ご協力ありがとうございました。
guest

回答1

0

自己解決

「SpotLightBase_B_y_03 : Rotation」の「Interpolation」が「Quaternion」になっていることが原因でした。
「Euler Angles」に変更後キーリダクションをおこなったところ、正しいキーリダクションが行われるようになりました。

キーリダクション後

投稿2022/08/19 01:08

flame_mori

総合スコア12

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問