「Rigidbodyで動かしたキャラがなぜかガクガクする」「PCによって移動速度が変わってしまう」——その原因、コードを書いた場所(UpdateかFixedUpdateか)にあるかもしれません。この2つはよく似ていますが、実行タイミングと役割には決定的な違いがあります。
この記事では、Update()とFixedUpdate()それぞれの仕組みを図解で整理し、「どの処理をどちらに書くべきか」を迷わず判断できるようになることを目指します。
この記事でわかること
UpdateとFixedUpdateの実行タイミングの違い(図解付き)- 「入力・見た目はUpdate、物理はFixedUpdate」の理由
Time.deltaTimeでフレームレートに依存しない動きを作る仕組み- Unity 6での
Rigidbody.velocityの変更点
実行タイミングの違い
Update()とFixedUpdate()の最も重要な違 いは、呼び出されるタイミングです。
Update()
- 毎フレーム1回呼び出されます。
- 実行間隔はフレームレートに依存します。つまり、PCの性能が高く、ゲームが秒間120フレーム(120fps)で動作していれば1秒間に120回、性能が低く30fpsしか出なければ1秒間に30回呼ばれます。実行間隔は一定ではありません。
FixedUpdate()
- 固定された時間間隔で呼び出されます。
- この間隔はデフォルトで0.02秒に設定されており、
Edit > Project Settings > TimeのFixed Timestepから変更できます。 - 実行間隔はフレームレートに依存しません。常に一定の間隔で呼び出されることが保証されています。
2つの呼び出し間隔をタイムラインで並べると、違いがひと目で分かります。

フレームレートが高い場合、Update()が数回呼ばれた後にFixedUpdate()が1回呼ばれる、という状況が発生します。逆にフレームレートが低い場合は、1フレームの間にFixedUpdate()が複数回呼ばれることもあります。
補足: つまり「
FixedUpdate()が1回も呼ばれないフレーム」も「複数回呼ばれるフレーム」も普通に存在します。このため、Input.GetKeyDown()のような「押した瞬間」を検知する処理をFixedUpdate()に書くと入力を取りこぼすことがあります。入力の検知は必ずUpdate()で行いましょう。
用途の使い分け
この実行タイミングの違いから、それぞれの用途は明確に分かれています。実際の開発シーンに当てはめたのが下の図です。「プレイヤーの見ている世界に関わることはUpdate、物理エンジンに任せることはFixedUpdate」と覚えておきましょう。

Update()の主な用途
フレームごとに状態が変化する可能性のある、時間的制約の少ない処理に適しています。Updateはフレームの描画と同期しているため、見た目に関する処理や入力の取得に最適です。
- 入力処理:
Input.GetKey()やInput.GetMouseButtonDown()など、プレイヤーからの入力を毎フレームチェックする。 - キャラクターの移動(物理演算を使わない場合):
transform.Translate()を使った単純な移動処理。 - タイマーやクールダウンの実装
- UIの更新
Update内で移動処理などを行う際は、 Time.deltaTime を乗算することを忘れないでください。Time.deltaTimeは、前のフレームから現在のフレームまでにかかった時間を表します。これを移動量に乗算することで、フレームレートが変動しても移動速度を一定に保つことができます。
イメージは「歩幅の自動調整」です。フレームが細かく刻まれる高fps環境では小さな歩幅でたくさん、フレームが粗い低fps環境では大きな歩幅で少なく進む——結果として、1秒後にはどちらも同じ位置に到着します。

using UnityEngine;
public class SimplePlayerMovement : MonoBehaviour
{
public float speed = 5f;
void Update()
{
// 入力を受け取る
float horizontal = Input.GetAxis("Horizontal"); // -1.0f から 1.0f
// Time.deltaTimeを乗算して、フレームレートに依存しない移動を実現
transform.Translate(Vector3.right * horizontal * speed * Time.deltaTime);
}
}
FixedUpdate()の主な用途
実行間隔が保証されているため、Rigidbodyに力を加える・速度を変えるといった 物理エンジンに渡す処理 はFixedUpdate()で行うのが基本です。Unityの物理エンジン(PhysX)は、FixedUpdate()のタイミングに合わせて更新処理を行っているためです。
Rigidbodyへの力の適用:rb.AddForce()やrb.AddTorque()を使ってオブジェクトに力を加える。Rigidbodyの速度の変更:rb.linearVelocityを直接変更する。- 物理的なキャラクターコントローラーの実装
補足: 速度を表すプロパティは、Unity 6(2023.3以降)で
velocityからlinearVelocityに名前が変わりました。古い記事やサンプルコードのrb.velocityはrb.linearVelocityと読み替えてください(旧名は非推奨警告が出ます)。
もしUpdate()内でRigidbodyに力を加え続けると、フレームレートの変動によって力が加わる回数が変わり、結果としてオブジェクトの動きが不安定になってしまいます。FixedUpdate()を使えば、常に一定の間隔で力が加わるため、再現性の高い安定した物理挙動が実現できます。
ここで1つ大事なのが、先ほどの補足との合わせ技です。 入力はUpdate()で読んで変数に保存し、FixedUpdate()では保存した値を使う ——この「Updateで読む→FixedUpdateで適用」が、物理で動かすキャラク ターの基本形になります。
using UnityEngine;
[RequireComponent(typeof(Rigidbody))]
public class PhysicsPlayerMovement : MonoBehaviour
{
public float moveForce = 50f;
private Rigidbody rb;
private float horizontal;
void Awake()
{
rb = GetComponent<Rigidbody>();
}
void Update()
{
// 入力の読み取りはUpdateで行い、変数に保存しておく
horizontal = Input.GetAxis("Horizontal");
}
void FixedUpdate()
{
// 保存した入力を使い、物理エンジンの更新に合わせて力を加える
rb.AddForce(Vector3.right * horizontal * moveForce);
}
}
補足:
FixedUpdate()の中でTime.deltaTimeを参照すると、固定刻み(Time.fixedDeltaTimeと同じ値)が返る仕様になっています。AddForce()や速度の代入のように物理エンジンに渡す処理には乗算不要ですが、FixedUpdate()内で自前の計算(位置や速度を自分で積み上げる処理)をする場合はTime.deltaTimeを掛けます。「FixedUpdateではdeltaTimeを一切使わない」と覚えるのは正確ではないので注意してください。
おまけ:先に知っておくと良いこと
使い分けをマスターしたら、次はこのあたりの知識が役立ちます。
- ライフサイクル全体の中での位置づけ:
UpdateやFixedUpdateは、Awake→Start→毎フレームループという大きな流れの一部です。全体像は ライフサイクルの記事 で図解しています。 - Rigidbodyそのものを深く知る: 力の加え方(
ForceMode