MonoBehaviourライフサイクルイベントとは?
MonoBehaviourを継承したクラスでは、AwakeやStart、Updateといった特定のタイミングでUnityエンジンから自動的に呼ばれるメソッドを定義できます。
これらは「ライフサイクルイベント」と呼ばれ、シーンの開始からオブジェクトの破棄までの一連の流れの中で、決まった順序で呼び出されます。
本記事では、その中でもよく使う「初期化2兄弟(Awake / Start)」と「更新3兄弟(Update / FixedUpdate / LateUpdate)」を取り上げ、それぞれの違いと使い分けを整理します。
主要なライフサイクルイベント
主要なライフサイクルイベントの実行順序は、ざっくり以下のとおりです。
| 順序 | メソッド | 呼ばれる回数 | 主な用途 |
|---|---|---|---|
| 1 | Awake | 1回 | 自身の初期化 |
| 2 | OnEnable | 有効化ごと | 購読・登録 |
| 3 | Start | 1回 | 他オブジェクトとの連携 |
| 4 | FixedUpdate | 固定間隔 | 物理演算 |
| 5 | Update | 毎フレーム | 入力・一般ロジック |
| 6 | LateUpdate | 毎フレーム | カメラ追従など |
| 7 | OnDisable | 無効化ごと | 購読解除 |
| 8 | OnDestroy | 1回 | クリーンアップ |

なお、MonoBehaviourのコールバック全般やUnityEventとの連携については別の記事で解説しています。
初期化2兄弟:Awake と Start
AwakeとStartはどちらも初期化のためのメソッドで、それぞれ1回だけ呼ばれます。
似ているように見えますが、呼び出されるタイミングと用途はけっこう違います。
Awake:自身の初期化
Awakeはスクリプトのインスタンスが生成された直後に呼ばれます。
シーンの読み込み時にすべてのGameObjectに対してAwakeが先に呼び出され、その後でStartに進みます。
この時点では他のGameObjectが初期化済みとは限りません。
そのためAwakeは、自身のコンポーネント取得や変数の初期化など、外部に依存しない処理を書く場所として使うのが基本です。
using UnityEngine;
public class Player : MonoBehaviour
{
private Rigidbody _rigidbody;
private void Awake()
{
// 自身にアタッチされたコンポーネントの取得
_rigidbody = GetComponent<Rigidbody>();
}
}
また、AwakeはGameObjectが非アクティブな状態でも、Instantiateされた直後に1回呼ばれます。
Start:他オブジェクトとの連携
Startは、すべてのAwakeとOnEnableの処理が終わってから、最初のフレーム更新が走る直前に呼ばれます。
この時点では、シーン内のすべてのオブジェクトのAwakeが完了しています。
他のGameObjectの参照取得や初期状態のやり取りは、Startに書くのが安全です。
using UnityEngine;
public class CameraFollower : MonoBehaviour
{
private Transform _target;
private void Start()
{
// 他オブジェクトの参照取得は Start で行う
var player = GameObject.FindWithTag("Player");
_target = player.transform;
}
}
なお、StartはGameObjectがアクティブにならない限り呼ばれません。非アクティブのままシーンに置かれているオブジェクトでは、Awakeだけ呼ばれてStartは呼ばれない、というケースもあります。
Awake と Start の比較
両者の違いを表にまとめておきます。
| 項目 | Awake | Start |
|---|---|---|
| 呼び出しタイミング | インスタンス生成直後 | 最初のフレーム更新直前 |
| 呼ばれる回数 | 1回 | 1回 |
| 非アクティブでも呼ばれるか | Instantiate時は呼ばれる | 呼ばれない |
| 他オブジェクトへのアクセス | 推奨されない | 推奨される |
| 主な用途 | 自身の初期化、GetComponent | 他オブジェクトの参照取得 |
迷ったら「コンポーネント取得はAwake、参照解決はStart」と覚えておけばだいたい事故りません。
更新3兄弟:Update / FixedUpdate / LateUpdate
ゲーム実行中に呼び出される更新系メソッドには、Update、FixedUpdate、LateUpdateの3種類があります。
名前は似ていても、呼び出されるタイミングと役割はそれぞれ別物です。
Update:入力取得と一般的なロジック
Updateは毎フレーム呼ばれる、もっとも基本的な更新メソッドです。
呼ばれる間隔はフレームレートに依存するので、フレーム間の経過時間はTime.deltaTimeから取得します。
入力の取得(Input.GetKeyDownなど)も、基本的にはここで行います。FixedUpdateは1フレームに複数回または0回呼ばれることがあり、GetKeyDownのような単発イベントを取りこぼす可能性があるためです。
using UnityEngine;
public class PlayerInput : MonoBehaviour
{
[SerializeField] private float _moveSpeed = 5f;
private void Update()
{
// 入力の取得は Update で行う
var horizontal = Input.GetAxis("Horizontal");
// フレームレートに依存しない移動量に変換
transform.Translate(Vector3.right * horizontal * _moveSpeed * Time.deltaTime);
}
}
FixedUpdate:物理演算
FixedUpdateは、物理演算用のタイムステップに合わせて固定間隔で呼ばれます。
デフォルトは0.02秒(50回/秒)ごとで、Edit > Project Settings > TimeのFixed Timestepから変更できます。

Rigidbodyに力を加える、MovePositionで位置を動かす、といった物理演算が絡む処理はここに書きます。
using UnityEngine;
public class PlayerPhysics : MonoBehaviour
{
[SerializeField] private float _force = 10f;
private Rigidbody _rigidbody;
private float _horizontal;
private void Awake()
{
_rigidbody = GetComponent<Rigidbody>();
}
private void Update()
{
// 入力の取得は Update で行い、値を保持しておく
_horizontal = Input.GetAxis("Horizontal");
}
private void FixedUpdate()
{
// Rigidbody への力の適用は FixedUpdate で行う
_rigidbody.AddForce(Vector3.right * _horizontal * _force);
}
}
FixedUpdateは描画フレームと独立して動くので、フレームレートが揺れても物理挙動を安定させやすいのが利点です。
その代わり、フレームレートが低いときは1フレーム中に複数回呼ばれることもあるので、その点には注意してください。
LateUpdate:他オブジェクト更新後の処理
LateUpdateは、シーン内のすべてのUpdateが呼ばれたあとに、毎フレーム実行されます。
「他のオブジェクトの更新結果を踏まえて処理したい」ときに使うメソッドです。
典型的な用途はカメラの追従処理ですね。
プレイヤーの位置をUpdateで動かしているとき、カメラの追従処理もUpdateに書いてしまうと、スクリプトの実行順序によってはプレイヤー移動の前にカメラが更新されてしまい、1フレーム前の位置を追ってしまいます。
これがカメラのカクつきを生む典型パターンです。次のセクションで詳しく見ていきます。
更新3兄弟の比較
| 項目 | Update | FixedUpdate | LateUpdate |
|---|---|---|---|
| 呼び出し間隔 | 毎フレーム | 固定間隔(既定0.02秒) | 毎フレーム |
| 経過時間の取得 | Time.deltaTime | Time.fixedDeltaTime | Time.deltaTime |
| 主な用途 | 入力、一般ロジック | 物理演算 | カメラ追従、他更新後の処理 |
| フレームレート依存 | あり | なし | あり |
この使い分けがハマりやすいのが、先ほど触れたカメラ追従です。具体的に何が起きて、LateUpdateへの切り替えでどう解決できるのかを次のセクションで見ていきます。
カメラ追従のカクつきとLateUpdateでの解決
更新3兄弟の使い分けがいちばん効いてくるのが、カメラ追従です。
問題:Update でカメラを追従させると
次のように、プレイヤー側のUpdateで位置を動かし、カメラ側のUpdateで追従させていたとします。
using UnityEngine;
// プレイヤー側:Update で移動
public class Player : MonoBehaviour
{
[SerializeField] private float _speed = 5f;
private void Update()
{
var horizontal = Input.GetAxis("Horizontal");
transform.Translate(Vector3.right * horizontal * _speed * Time.deltaTime);
}
}
using UnityEngine;
// カメラ側:Update で追従(NG例)
public class CameraFollow_NG : MonoBehaviour
{
[SerializeField] private Transform _target;
[SerializeField] private Vector3 _offset = new Vector3(0f, 2f, -5f);
private void Update()
{
// 実行順序によっては Player の Update より先に呼ばれる
transform.position = _target.position + _offset;
}
}
Update同士の実行順序はオブジェクトごとに決まっておらず、Unityからは未定義として扱われます。
もしカメラ側のUpdateがプレイヤー側より先に呼ばれてしまうと、カメラは前フレームのプレイヤー位置を追ってしまいます。
この1フレームのズレが、映像のカクつきやジッターになって現れるわけです。
解決:LateUpdate に移す
カメラ追従の処理をLateUpdateに移すと、すべてのUpdateが完了したあとに呼ばれるので、プレイヤーの最新位置を確実に追えます。
using UnityEngine;
// カメラ側:LateUpdate で追従(OK例)
public class CameraFollow : MonoBehaviour
{
[SerializeField] private Transform _target;
[SerializeField] private Vector3 _offset = new Vector3(0f, 2f, -5f);
private void LateUpdate()
{
// すべての Update 完了後に追従
transform.position = _target.position + _offset;
}
}
カメラ追従以外にも、IK処理や、複数オブジェクトの位置に追従するエフェクトなど、「他オブジェクトの更新結果を使いたい処理」はLateUpdateに書くのがセオリーです。
実行順序の罠とScript Execution Order
ここまで見てきたように「AwakeはStartより先」「UpdateはLateUpdateより先」といった種類間の順序は確定しています。一方で、同じ種類のメソッド同士の順序は基本的に未定義です。
例えばシーン内にEnemyAとEnemyBという2つのスクリプトがあるとき、どちらのUpdateが先に呼ばれるかは保証されません。
Script Execution Order で順序を指定する
どうしても順序を制御したいときは、Edit > Project Settings > Script Execution Orderからスクリプト単位で実行順序を指定できます。値が小さいほど早く呼ばれ、Default Timeのスクリプトは中央のタイミングで呼ばれます。

DefaultExecutionOrder 属性で指定する
スクリプト側に属性を付けることでも順序を指定できます。
using UnityEngine;
// 通常より早いタイミングで実行する
[DefaultExecutionOrder(-100)]
public class GameInitializer : MonoBehaviour
{
private void Awake()
{
// 他のスクリプトより先に初期化を行いたい処理
}
}
ただし、実行順序に依存しすぎた設計は後から修正しづらくなるので、できるだけ避けたいところです。
基本は「Awakeで自身を初期化」「Startで参照を解決」を守り、それでも順序が必要なときだけScript Execution Orderを使う、というのがよいでしょう。
補足:OnEnable / OnDisable / OnDestroy
最後に、初期化・更新系とあわせて押さえておきたいライフサイクルメソッドも軽く紹介しておきます。
OnEnable / OnDisable
OnEnableはGameObjectまたはコンポーネントが有効になるたび、OnDisableは無効になるたびに呼ばれます。
Awakeの直後に最初のOnEnableが呼ばれ、その後にStartが続く流れです。
イベントの購読登録はOnEnable、解除はOnDisable、と覚えておくのがセオリーです。
using UnityEngine;
public class EventListener : MonoBehaviour
{
private void OnEnable()
{
// 有効化時にイベントを購読
Application.lowMemory += OnLowMemory;
}
private void OnDisable()
{
// 無効化時に必ず解除
Application.lowMemory -= OnLowMemory;
}
private void OnLowMemory()
{
Debug.Log("メモリ不足の通知を受け取った");
}
}
OnDestroy
OnDestroyは、オブジェクトが破棄される直前に1回呼ばれます。購読解除やDisposeが必要なリソースの後始末はここで行います。
ただし、Awakeが一度も実行されていないオブジェクト(一度もアクティブになっていないGameObject)ではOnDestroyは呼ばれません。
例えばシーンに非アクティブで置かれたオブジェクトを、一度もアクティブにせず破棄した場合、Awakeが走っていないためOnDestroyもスキップされます。
まとめ
MonoBehaviourのライフサイクルイベントは、Unityのゲーム開発で土台になる仕組みです。
ざっくり整理すると、自身の初期化やコンポーネント取得はAwake、他オブジェクトの参照解決はStart、入力や一般ロジックはUpdate、物理演算はFixedUpdate、カメラ追従のように他オブジェクトの更新後に走らせたい処理はLateUpdate。
これが基本の住み分けです。
同じ種類のメソッド同士の実行順序は未定義なので、どうしても順序が必要なときだけScript Execution OrderやDefaultExecutionOrder属性で制御すれば十分です。
どのメソッドにどんな処理を書くかを意識するだけで、原因不明のバグやカクつきはかなり減らせます。ご自分のプロジェクトでも、ライフサイクルの使い分けを一度見直してみてください。



