Unity上でMMDモデルを独自アニメーションで走らせる
MMDモデルをRoot移動の無い、独自のモーションで走らせる方法についてです。この記事は以前に書いたUnity内でMMDモデルを自由に走らせる手軽な方法 の続き的な位置づけです。
目次
MMDモデルおよびモーションの登録
MMDモデルとモーションを登録します。
基本的にはMMD4Mecanimを使用してMMDモデルにUnityで踊って頂いてみた。のPMX2FBXを行う を参考にモデルを登録すればOKです。その際、VMDを登録したい場合はVMDにモーションを登録して使用します。
ちなみにUIが以前と比べてだいぶスッキリしているので、かなり分かりやすくなっています。基本的には、以下の操作を行えばOKです。
- MMD4Mecanimをインポート
- MMDモデルをProjectビューに突っ込む
- Projectビューに(モデル名)MMD4Mecanimが自動的に作成されるので、選択
- Inspectorビューで利用規約とか同梱されているReadMeを読んで同意
- Processを押す(だいぶUIがスッキリ)
Unityの他のモーション、たとえばユニティちゃんのモーションを使用したい場合は、作成されたFBXを選択後、InspectorでRigを選択し、AnimationTypeをHumanoidに設定します。モーション時に空気椅子のポーズをとる場合、だいたいこのあたりの設定です。
本当はモーション側もVMDから持ってきて紹介しようと思いましたが、探すのが面倒になったのでモーションはAssetStoreから拝借します。
RootMotionとアニメーション
RootMotionがあるアニメーションならば、ApplyRootMotionでキャラクターの位置を動かす事が出来ます。アニメーションで動かすことが出来るので、「蹴りはじめは加速」のような緩急のあるモーションをデザイナーの力で設定出来て。
ただ、現状ゲームで一般的なのはRootMotionのないアニメーションで、その場でバタバタするタイプです。上がRootMotionが動くアニメーション、下が動かないアニメーションです。その場でバタバタ動いているのが確認出来ます。
RootMotionの無いモーションはApplyRootMotionで動かす事が出来ないので、スクリプトで動かします。
スクリプトでキャラクターの位置を動かす
スクリプトとAnimationでキャラクターの位置を動かす場合、OnAnimatorMoveコールバック内で動かすのがAnimator的には良いです。
この処理をコンポーネントに記述すると、AnimatorのApplyRootMotionが消えHandled by scriptと表示されます。
あとはOnAnimatorMove内で移動の処理を記述してやればOKです。キャラクターの移動はTransformでやると壁を貫通するので、CharacterControllerやRigidbodyを使用し障害物を貫通しないようにします。
ちなみにRootMotionを使用したい場合、animator.rootPositionやanimator.rootRotationを使用すると、アニメーションの移動が取得できます。
この実装をせずApplyRootMotoinにチェックが入っている場合、ルートの移動量で移動します。これ、直線移動は良いですが回転が面倒です。
マップから落下するのを絶対に防ぎたい場合は、NavmeshAgent.Moveを使うアイディアも良い気がします。
移動量に合わせてモーションを切り替える
キャラクターの移動量に合わせてモーションを切り替えます。状態によりAnimator.CrossFadeを使用してアニメーションを切り替えるのも良いのですが、今回はBlendTreeを使用します。
まず空のAnimationClipを切り替えるアニメーション分作ります。Animatorに内蔵してしまうとアニメーションがすっきりします。
ParameterにSpeedを設定し、このパラメータが0.1以上になった時にRunning・以下の場合はIdleするようにします。BlendTreeの設定はNavmeshのAI経路探索とAnimatorのアニメーションを連動させる もどうぞ。
最後にAnimatorOverrideControllerを使用してAnimatorのアニメーションを上書きします。Controllerに先ほど作成したAnimationControllerを設定し、上書きしたいAnimationClipで更新します。
これはAnimationControllerで直接設定しても良いのですが、個人的にはこっちの方がAnimationControllerを使いまわしやすいので好きです。
あとは移動時に移動距離に合わせてanimator.SetFloatを設定してやると、移動量に合わせてモーションが切り替わります。
ステートを増やすことで、ジャンプや落下中・着地のモーション切り替えもスムーズに行えるようになりますが、これはこれで長いのでまた今度。
移動先を向く
移動先を向いてもらいます。単純にCharacterControllerから移動量を持ってきて、移動先にキャラクターを回転させるだけです。
移動先=キャラクターの向いてる方向では無い場合は違う実装も出来ます。
if (direction != Vector3.zero) {
var velocity = characterController.velocity;
velocity.y = 0;
transform.rotation = Quaternion.LookRotation(velocity);
}
スクリプト
今回のコードです。このコードをシーンに配置したモデルに設定すれば、たぶんアニメーションします。モーションが切り替わらない場合はAnimationControllerの設定が間違ってる、空気椅子したらモーションの設定が間違ってる、って感じです。
Resetでやってるので、【Unity】コンポーネントを設定したフィールドを非表示にする でフィールドを非表示にします。
関連
今回は東北ずん子のイラスト/3Dデータのデータをお借りしました。SDずん子ちゃん可愛い!