前提・実現したいこと
Unityで3Dモデル(Unitychan)を使用して、アニメーターでのモーション中に、各関節のクォータニオンに係数をかけることで、同じアニメーションでも動きを大きさを大きくしたり小さくしたりするためのスクリプトを書きたいです。
試したこと
Animator.GetBoneTransformでその時点のボーン情報などを取得できることが分かったのですが、取得した後に関節角度に係数をかけて3Dモデルに返すにはどうすればいいのかわかりませんでした。
補足情報(FW/ツールのバージョンなど)
Unity2019.4.3f1を使用中です。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答2件
0
ベストアンサー
ボーンの動きを直接的に制御するのは面倒そうな気配がして、代わりに下記のようにHumanPoseHandlerを経由して操作してみたところ...
C#
1using UnityEngine; 2 3namespace AmplifyAnimation 4{ 5 [RequireComponent(typeof(Animator))] 6 public class AnimationAmplifier : MonoBehaviour 7 { 8 public bool applyRootMotion = true; 9 [Range(0.0f, 3.0f)] public float amplitude = 1.0f; 10 private Animator animator; 11 private HumanPoseHandler poseHandler; 12 private HumanPose pose; 13 private Vector3 rootPosition; 14 private Quaternion rootRotation; 15 private float[] initialMuscles; 16 17 private void Awake() 18 { 19 this.animator = this.GetComponent<Animator>(); 20 21 // ポーズを取得・操作するためのハンドラーを取得する 22 this.poseHandler = new HumanPoseHandler(this.animator.avatar, this.transform); 23 24 // 初期状態でのマッスル値を覚えておき、これを基準の姿勢とする 25 var t = this.transform; 26 this.rootPosition = t.position; 27 this.rootRotation = t.rotation; 28 t.SetPositionAndRotation(Vector3.zero, Quaternion.identity); 29 this.poseHandler.GetHumanPose(ref this.pose); 30 t.SetPositionAndRotation(this.rootPosition, this.rootRotation); 31 this.initialMuscles = this.pose.muscles.Clone() as float[]; 32 } 33 34 private void OnAnimatorMove() 35 { 36 var t = this.transform; 37 this.rootPosition = t.position; 38 this.rootRotation = t.rotation; 39 if (!this.applyRootMotion) 40 { 41 return; 42 } 43 44 // もしルートモーションの適用が必要なら、このタイミングで処理しておく 45 // このとき、動く量をamplitudeに応じて増減させる 46 var deltaPosition = Vector3.LerpUnclamped( 47 Vector3.zero, 48 this.animator.deltaPosition, 49 this.amplitude); 50 var deltaRotation = Quaternion.SlerpUnclamped( 51 Quaternion.identity, 52 this.animator.deltaRotation, 53 this.amplitude); 54 this.rootPosition += deltaPosition; 55 this.rootRotation = deltaRotation * this.rootRotation; 56 } 57 58 private void LateUpdate() 59 { 60 var t = this.transform; 61 62 // Animatorが設定した現在のポーズを取得し... 63 t.SetPositionAndRotation(Vector3.zero, Quaternion.identity); 64 this.poseHandler.GetHumanPose(ref this.pose); 65 t.SetPositionAndRotation(this.rootPosition, this.rootRotation); 66 67 // 初期ポーズとの差分をamplitudeに応じて増幅して... 68 var muscles = this.pose.muscles; 69 for (var i = 0; i < muscles.Length; i++) 70 { 71 muscles[i] = Mathf.LerpUnclamped(this.initialMuscles[i], muscles[i], this.amplitude); 72 } 73 74 // 修正したポーズを適用する 75 this.poseHandler.SetHumanPose(ref this.pose); 76 } 77 } 78}
下図のようになりました。
動きを抑える方向でしたら使えなくはないかもしれませんが、激しくする方向だと関節の向きがヤバいことになってしまいますね...
動きの激しさをさまざまに調整したいのでしたら、やはり順当な方針としては、激しい動きのアニメーションをあらかじめ用意しておいた上でブレンドツリーだとかを使ってモーションを混ぜ合わせるのがいいんじゃないかと思います。
投稿2020/07/20 22:29
総合スコア10811
0
ボーンが Animation で設定された位置、角度に移動してから描画されるまでの間に角度を操作したいということになると思いますが、ひょっとしたら OnAnimatorMove でそのタイミングを取れるかもしれません。
リファレンスを見ると Root Motion がどうとか書いてあるのでルートモーションを使ってないと呼ばれないかもしれないし、自分ではやろうと思わないので試してみてください。
投稿2020/07/20 22:09
総合スコア5308
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/07/20 23:12