Time.deltaTime と Translate を正しく使う

――「1フレームで移動させたい距離」を渡すだけ

TL;DR

  • 動かしたい距離は 距離 = 速さ × 時間
  • Time.deltaTime は「直前フレームからの経過時間(秒)」。
  • transform.Translate(変位ベクトル) の引数は このフレームで実際に動かす距離(+向き)
  • だから Translate(方向 × speed × Time.deltaTime) と書けば、PC性能が違っても、同じ時間で同じ距離だけ動く。
// 右に 1 m/s で等速移動(フレーム非依存)
public float speed = 1f; // m/s

void Update()
{
    // transform.Translate(1フレームで実際に動かす距離 = 速さ x 時間)
    transform.Translate(Vector3.right * speed * Time.deltaTime);
}

1. Translate の引数は「このフレームで動かす変位」

Translate の引数は 変位ベクトル(= 大きさが距離、向きが進行方向)。

わかりやすく言い換えると――

transform.Translate(1フレームで移動させたい距離);

となります。上のコードは「右向きに、1フレームで speed × deltaTime メートルだけ動かす」という意味になります。

  • 方向:Vector3.right(ワールドの+X方向)
  • 速さ:speed(m/s)
  • 時間:Time.deltaTime(s)→ 距離(m) = m/s × s

既定ではローカル座標系で移動します。ワールド基準にしたいときは第2引数で Space.World を指定します。

transform.Translate(Vector3.right * speed * Time.deltaTime, Space.World);

フレームレート(FPS)はPCによって変わります。

deltaTime を掛けないと、FPSが高いほど1秒あたりの移動回数が増え、結果として速くなってしまいます。

deltaTime を掛けると、1フレームの移動距離がそのフレームの経過時間に比例するため、1秒後の位置が一定になります。


3. よくある別表現との対応

// 本質的に同じ(Translate は内部で position に変位を加算している)
transform.position += Vector3.right * speed * Time.deltaTime;
  • Translate は「変位を渡す
  • position += は「今の位置に変位を足す」どちらも同じ考え方で、引数は “このフレームの移動量” です。

4. 斜め移動で速さが増えないようにする(正規化)

public float speed = 3f;

void Update()
{
    float x = Input.GetAxisRaw("Horizontal");
    float z = Input.GetAxisRaw("Vertical");
    Vector3 dir = new Vector3(x, 0f, z).normalized;  // ← ここが大事
    transform.Translate(dir * speed * Time.deltaTime, Space.World);
}
  • normalized を付けないと、斜め(1,0,1)が縦横より速くなります。
  • 正規化して方向だけを取り出し、速さは speed に任せます。

5. 物理オブジェクト(Rigidbody)のときは?

物理は FixedUpdate と Time.fixedDeltaTime を使います。

Rigidbody を持つオブジェクトは、Transform を直接動かさず Rigidbody.MovePosition が基本です。

[RequireComponent(typeof(Rigidbody))]
public class RigidbodyMover : MonoBehaviour
{
    public float speed = 2f;    // m/s
    Rigidbody rb;

    void Awake() => rb = GetComponent<Rigidbody>();

    void FixedUpdate()
    {
        Vector3 delta = Vector3.right * speed * Time.fixedDeltaTime;
        rb.MovePosition(rb.position + delta);
    }
}

NG例

  • Update 内で AddForce/MovePosition など物理操作をする
  • FixedUpdate で Time.deltaTime を使う(→ 正しくは fixedDeltaTime)

6. ミス防止チェックリスト

  • deltaTime を掛け忘れていないか
  • deltaTime を二重に掛けていないか(どこかで既に掛けているのに再度掛ける)
  • Translate の第2引数(World/Self)は意図通りか
  • Rigidbody を Transform で動かしていないか
  • 速度の単位は m/s で説明できるか(インスペクターに [Tooltip(“m/s")] 推奨)

7. 学習課題(体験で理解する)

課題A:deltaTime の有無を比較

  1. サンプルを deltaTime あり/なしで切り替える
  2. Application.targetFrameRate = 30/60/120; を変えながら再生
  3. 1秒後の transform.position.x を Debug.Log で比較期待:deltaTime あり → ほぼ同じ位置、なし → FPS に比例してズレる

課題B:ローカル/ワールドの違い

  • Space.Self と Space.World を切り替え、オブジェクトを回転させたときの進行方向を観察

8. まとめ(言い換えで覚える)

  • Translate(1フレームで移動させたい距離)
  • その距離は 方向 × 速さ × 経過時間
  • deltaTime を掛ける=フレーム差を吸収する
  • 物理は FixedUpdate + fixedDeltaTime + MovePosition

付録:そのまま使えるテンプレ

// 等速移動(Transform/ワールド右)
public class MoveRight : MonoBehaviour
{
    [Tooltip("m/s")] public float speed = 1f;

    void Update()
    {
        transform.Translate(Vector3.right * speed * Time.deltaTime, Space.World);
    }
}
// 入力で等速(正規化で斜めも一定速)
public class MoveByInput : MonoBehaviour
{
    public float speed = 3f;

    void Update()
    {
        float x = Input.GetAxisRaw("Horizontal");
        float z = Input.GetAxisRaw("Vertical");
        Vector3 dir = new Vector3(x, 0, z).normalized;
        transform.Translate(dir * speed * Time.deltaTime, Space.World);
    }
}
// 物理で等速(Rigidbody)
[RequireComponent(typeof(Rigidbody))]
public class MoveRightPhysics : MonoBehaviour
{
    public float speed = 1f;
    Rigidbody rb;

    void Awake() => rb = GetComponent<Rigidbody>();

    void FixedUpdate()
    {
        rb.MovePosition(rb.position + Vector3.right * speed * Time.fixedDeltaTime);
    }
}

訪問数 4 回, 今日の訪問数 4回

C#,Time.deltaTime,Unity

Posted by hidepon