Skip to content
第09回 3D探索2

3 / 4 実際の移動速度を渡す ​

このステップの目的

入力値ではなく、キャラクターの実際の移動量からAnimatorのSpeedを設定する

移動量から速度を求める ​

速度は「1秒あたりに進む距離」です。同じ0.1だけ進んでも、0.02秒で進んだ場合と0.1秒かかった場合では速さが違います。前回位置との差を、その間に経過した秒数で割ります。

位置の変化の長さ経過時間実際の速度runSpeedが5のときのSpeed
00.02秒00
0.050.02秒2.5単位/秒0.5
0.10.02秒5単位/秒1

runSpeed はRunへ対応させる基準速度で、0より大きい値を使います。距離の単位はUnityのワールド座標単位です。actualSpeed / runSpeed は単位のない比率なので、前のステップで設定した0〜1へ対応づけられます。

前回位置をそろえてから計測する ​

controller は移動するキャラクター、animator はモデルのAnimatorへの参照です。previousPosition はフレームをまたいで保持するVector3のメンバ変数にします。開始位置を決めた後、最初の計測前に previousPosition = controller.transform.position; を一度実行します。初期値の原点から測ると、出現位置までの距離を最初の移動と誤認します。

毎フレームの計測は、そのフレームの移動処理が終わってから行います。Updateで移動する構成ならLateUpdateで計測します。同じ処理内で行うなら、移動→計測→前回位置の保存、の順です。

csharp
Vector3 movement = controller.transform.position - previousPosition;
float actualSpeed = Time.deltaTime > 0f
    ? movement.magnitude / Time.deltaTime
    : 0f;
animator.SetFloat("Speed", Mathf.Clamp01(actualSpeed / runSpeed));
previousPosition = controller.transform.position;

magnitude は位置差のベクトルの長さ、Clamp01 は値を0〜1に収める関数です。この対応では基準速度を超えてもRunを使います。経過時間が0の場合は割り算せず0にします。再出現やワープで位置を瞬間移動したときも、その直後にpreviousPositionを更新し、その移動を歩行速度として数えないようにします。

入力があっても壁に当たって動いていなければ、見た目は走らせません。実際の状態を見た目へ反映することが重要です。

速度を比較する ​

最初は停止・半速・基準速度で、表と同じSpeedになるかを確認します。次に同じ移動速度を保ち、Blend Treeのクリップの再生速度倍率だけを変えて、足滑りが少ない値を探します。Speedは混ぜる割合、再生速度倍率は足を動かす速さです。一度に両方を変えないようにします。

チェックリスト
  • 実際の移動量から速度を求めている
  • 最初の計測とワープの際に前回位置をそろえる理由を説明できる
  • 0.05単位を0.02秒で進んだとき、基準速度5ならSpeedが0.5になると計算できる
  • 壁に向かって入力しても走り続けない
  • 移動速度とモーション速度を比較調整した