Unityでキャラクターの斜め移動がなんだか早い。これを解消する簡単な方法。

少しづつUnityに触れ、手探りではありますが、なんとなく作り方が見えてきました。

もともとのテストプロジェクトも理解が進むにつれて、だいぶ内容が変わったのでどこかで整理し掲載したいところですが、手触り面でキャラクターの移動に違和感を感じたので修正しました。

気がつけばユニティちゃんもSD化しています(笑)

ようやくUpdateとFixedUpdateの違いがわかり、移動系の処理が次のような感じになっていました。

// 以下、キー入力などはUpdateで受け取り
void Update() {

    h = Input.GetAxis("Horizontal");              // 入力デバイスの水平軸をhで定義
    v = Input.GetAxis("Vertical");                // 入力デバイスの垂直軸をvで定義

}

// 移動系の処理はFixedUpdate内で行う.
void FixedUpdate() {

    playerPosition = transform.position; //プレイヤー位置情報を更新

    // 上下のキー入力でキャラクターを移動させる
    transform.localPosition += new Vector3(h, 0, v) * forwardSpeed * Time.fixedDeltaTime;

    //移動後のキャラクターが前回からどの方向に進んだか差分を取得する
    Vector3 diff = transform.position - playerPosition;

    if (diff.magnitude > 0.01f) {
        //差異があった場合にのみ向きを変更する
        transform.rotation = Quaternion.LookRotation(diff);
    }

}

問題点はココ

transform.localPosition += new Vector3(h, 0, v) * forwardSpeed * Time.fixedDeltaTime;

キー入力から横移動だけの際は、hが1でvが0。このベクトルに対して、移動速度などをかけてキャラを動かしています。斜め移動の際は、hが1でvも1……とより大きなベクトルが入力されてくるので、より大きく進んでしまうといった単純な問題でした。

対応法

幸いにも元々のhとvの最大値が1なので、こんな時は、ノーマライズですね。

transform.localPosition += new Vector3(h, 0, v).normalized * forwardSpeed * Time.fixedDeltaTime;

いい感じに値を正規化してくれます。

Debug.Log(new Vector3(1, 0, 1).normalized);
(0.7, 0.0, 0.7)

Debug.Log(new Vector3(1, 0, 0).normalized);
(1.0, 0.0, 0.0)

NavMeshAgentを使って、敵キャラを自動追従させる際にも、ベクトルの正規化させた後、同じ移動処理に値を突っ込んで上げるといい感じになります。

このあたりは複雑なので別途まとめていきたいなぁと思ってます。

この記事はユニティちゃんライセンス条項の元に提供されています。
© Unity Technologies Japan/UCL