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 の有無を比較
- サンプルを deltaTime あり/なしで切り替える
- Application.targetFrameRate = 30/60/120; を変えながら再生
- 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回
ディスカッション
コメント一覧
まだ、コメントがありません