3 / 4 実際の移動速度を渡す
入力値ではなく、キャラクターの実際の移動量からAnimatorのSpeedを設定する
移動量から速度を求める
速度は「1秒あたりに進む距離」です。同じ0.1だけ進んでも、0.02秒で進んだ場合と0.1秒かかった場合では速さが違います。前回位置との差を、その間に経過した秒数で割ります。
| 位置の変化の長さ | 経過時間 | 実際の速度 | runSpeedが5のときのSpeed |
|---|---|---|---|
| 0 | 0.02秒 | 0 | 0 |
| 0.05 | 0.02秒 | 2.5単位/秒 | 0.5 |
| 0.1 | 0.02秒 | 5単位/秒 | 1 |
runSpeed はRunへ対応させる基準速度で、0より大きい値を使います。距離の単位はUnityのワールド座標単位です。actualSpeed / runSpeed は単位のない比率なので、前のステップで設定した0〜1へ対応づけられます。
前回位置をそろえてから計測する
controller は移動するキャラクター、animator はモデルのAnimatorへの参照です。previousPosition はフレームをまたいで保持するVector3のメンバ変数にします。開始位置を決めた後、最初の計測前に previousPosition = controller.transform.position; を一度実行します。初期値の原点から測ると、出現位置までの距離を最初の移動と誤認します。
毎フレームの計測は、そのフレームの移動処理が終わってから行います。Updateで移動する構成ならLateUpdateで計測します。同じ処理内で行うなら、移動→計測→前回位置の保存、の順です。
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になると計算できる
- 壁に向かって入力しても走り続けない
- 移動速度とモーション速度を比較調整した