【Unity】Navmeshで取得した経路をApplyRootMotionで移動させる手っ取り早い方法
今回はNavmeshとApplyRootMotionを組み合わせて動かす手っ取り早い方法についてです。
なお、逆のパターン(Nameshを主としてAnimatorを動かす)場合は、こちら。
ApplyRootMotionとNavmesh
UnityのアニメーションシステムであるMecanimには、ApplyRootMotoinという機能があります。これは、アニメーションの移動値を元にキャラクターの座標を移動させるという物です。上手く使うことで、キャラクターを走らせる際「蹴り始めは加速」「着地時に減速」といった、緩急のある移動が可能になります。
一方Navmeshはと言えば、最大スピードと加速等で移動し、目的地付近になると減速します。そのため、速度とモーションの速度が一致していない場合、足踏みしているような不自然な挙動になる事があります。
要するにAniamtorとNavmesh双方ともに動きを管理している訳です。今回はその2つを組み合わせて使ってみます。
NavmeshAgentが設定されたオブジェクトの移動を止める
今回の目的はNavmeshではなくAnimatorのApplyRootMotoin主導で動かす事です。なので、Navmeshの移動自体を止めてしまいます。
NavmeshAgentを設定したオブジェクトの移動を止めるには、updatePosition = false;
を使用します。
但し、上のGifアニメのようにNavmeshAgent自体の動きが止まる訳ではない点に注意する必要があります。
NavmeshAgentと動きが一致していないと曲がって欲しい所で曲がってくれないので、NavmeshAgentの位置を、agent.nextPosition = transform.position;
のような形で現在の座標に設定します。
後は、ApplyRootMotionを設定したアニメーションで移動させてやれば、ある程度パスに沿ってキャラクターが移動してくれます。
終了距離が近づいてきたら、動かないアニメーションに切り替える
キャラクターが移動してくれるのは良いのですが、Navmeshによる移動系の処理を殆ど切っている為、AutoBraking等の機能によりブレーキを踏んでくれません。
なので、停止するアニメーションを設定します。まずは下のようにIsStopならIdleする、といった設定にします。
後は、remainingDistance (目標地点までの距離)がstoppingDistance(停止する位置)より近くなっていたら、アニメーションをIdleに切り替えます。
animator.SetBool ("IsStop", agent.remainingDistance < agent.stoppingDistance);
これで、目標地点に近づいたら停止します。
一応、NavmeshAgentのAuto Breaking設定は使わないのでチェックボックスを外しておくが吉です。
要するに
要するに、
- 前進後退等はApplyRootMotoin
- 旋回はNavmeshAgentにお任せ
- 停止はNavmeshAgentの設定を元に、ApplyRootMotionで動かないキャラに切替
みたいな感じです。
旋回部分もApplyRootMotoinでやる場合、NavmeshAgentのupdateRotation = false;で回転を制限して、その上で agent.desiredVelocityを見て曲がるアニメーションを設定すれば良いかなと。