この記事について

この記事は私がゲーム制作・学習等で学んだ知識を元にライフサイクルの考え方をわかりやすく説明していきます。

この記事で学べること

  • Unityのライフサイクルの全体像
  • Awake()・Start()・Update()・FixedUpdate()・LateUpdate() の違いと使い分け
  • 初期化・物理処理・カメラ制御の正しい配置方法
  • ライフサイクルを考慮した最適なコード設計

Unityのイベント関数・ライフサイクルの流れ

Unityでは、GameObjectの生成から破棄まで、さまざまなイベント関数が呼ばれます。以下は主な関数とその役割です。FixedUpdateは描画1フレームにつき0回・1回・複数回と回数が変わるため、この一覧が毎フレーム1回ずつ順に実行されるわけではありません。

Unityの主なコールバックの概念図。同じMonoBehaviourの初回はAwake、OnEnable、Startの順。UpdateとLateUpdateはフレームごと、FixedUpdateは一定間隔で描画1フレーム内に0回・1回・複数回実行される。
図:初回の順序は同じMonoBehaviour内の関係です。別オブジェクトのAwakeより先にOnEnableが呼ばれる場合があるため、全体で一律の順序とは考えません。FixedUpdateも描画フレームと1対1ではありません。Unity公式「イベント関数の実行順序」をもとに作成した概念図です。
  1. Awake() :アクティブなGameObjectの初期化時に一度だけ実行。非アクティブなら初めてアクティブになったとき。
  2. OnEnable() :GameObjectがアクティブで、スクリプトも有効な状態になったときに呼ばれる。この状態になるたびに実行。
  3. Start() :Awakeのあと、GameObjectがアクティブでスクリプトが有効なとき、最初のUpdateの前に一度だけ実行。
  4. Update() :毎フレーム実行。プレイヤー入力など。
  5. FixedUpdate() :物理演算向け。一定間隔で実行。
  6. LateUpdate() :Updateの後に実行。カメラ制御などに最適。
  7. OnDisable():オブジェクトが無効化されたときに呼ばれる。
  8. OnDestroy() :破棄直前のクリーンアップ処理に使用。

※ 詳しいライフサイクルを知りたい方は公式サイトをご確認ください。
公式サイトリンク:イベント関数の実行順序

Awake() vs Start()の違い

Awake()

  • 実行タイミング:アクティブなGameObjectの初期化時に一度。非アクティブなら初めてアクティブになったとき
  • 主な用途:依存関係の初期化、シングルトン管理
  • 注意点:GameObjectが非アクティブな間は実行されない。GameObjectがアクティブなら、スクリプトのenabledがfalseでも実行される

Start()

  • 実行タイミング:Awakeの後、初めてUpdateが呼ばれる直前に一度
  • 主な用途:コンポーネント取得、初期状態設定
  • 注意点:GameObjectがアクティブで、スクリプトが有効になるまで実行されない

オブジェクトの初期化の適切な処理方法

オブジェクトを適切に初期化するには、Awake() と Start() の使い分けが重要です。以下は使い分けを示す学習用の抜粋です。GameManagerの例は、Rigidbodyを付けたルートGameObjectに1つだけ配置する前提で、重複生成を防ぐ処理などは省略しています。各コードはusing UnityEngine;を宣言したスクリプトで使い、後半のメソッド例はMonoBehaviourを継承したクラス内に記述してください。

➡ Awake()で自身の参照取得や初期化を行う
➡ Start()で、他のオブジェクトのAwakeが済んだことを前提とする処理を行う(シーン開始時のアクティブなオブジェクト同士)

public class GameManager : MonoBehaviour
{
    public static GameManager instance;

    //Awake() の使用例(依存関係の初期化)    
    void Awake()
    {
        instance = this;
        DontDestroyOnLoad(gameObject);
    }

    //Start() の使用例(オブジェクトの初期設定)
    void Start()
    {
        Rigidbody rb = GetComponent<Rigidbody>();
        rb.mass = 2.0f;
     }
}

Update() と FixedUpdate() の違い

Update()

  • 実行頻度:毎フレーム(フレームレート依存)
  • 主な用途:ユーザー入力、アニメーション
//Update() の使用例(プレイヤーの移動)
void Update()
{
    float move = Input.GetAxis("Horizontal");
    transform.position += new Vector3(move, 0, 0) * Time.deltaTime;
}


※ Transformについては以下のサイトを参考にしてください。

FixedUpdate()

  • 実行頻度:一定間隔(Time.fixedDeltaTime)。描画1フレームにつき0回・1回・複数回になる
  • 主な用途:物理演算(Rigidbody)
//FixedUpdate() の使用例(Rigidbody の移動)
void FixedUpdate()
{
    Rigidbody rb = GetComponent<Rigidbody>();
    rb.velocity = new Vector3(0, 0, 5);
}


※ Rigidbodyの例は同じGameObjectにRigidbodyを付け、速度を設定する場合はIs Kinematicをオフにしてください。速度そのものの代入にはTime.deltaTimeを掛けません。Rigidbody、Colliderについては以下の記事を参考にしてください。

物理演算を適切に処理する方法

物理演算を扱う場合、FixedUpdate()を使用することで安定したシミュレーションが可能 です。

➡ 継続的にRigidbodyを動かす処理はFixedUpdateで行う
➡ FixedUpdate内のTime.deltaTimeはTime.fixedDeltaTimeと同じ値

//FixedUpdate() の使用例(Rigidbody の移動)
void FixedUpdate()
{
    Rigidbody rb = GetComponent<Rigidbody>();
    rb.velocity = new Vector3(0, 0, 5);
}

LateUpdate() の使い方

LateUpdate()

  • 実行タイミング:Update後
  • 主な用途:カメラ追従、演出の後処理。以下の抜粋はplayer(Transform)とoffset(Vector3)を別途設定した前提
void LateUpdate() {
    transform.position = player.position + offset;
}

ライフサイクルの使い分けまとめ

関数名実行タイミング主な用途備考
Awake()初回の初期化時(1回)自身の初期化非アクティブなら初回有効化まで待機
Start()初回Updateの前初期状態の設定GameObjectとスクリプトの両方が有効
Update()毎フレームユーザー入力などフレームレート依存
FixedUpdate()一定間隔Rigidbodyの制御など物理演算向け
LateUpdate()Updateの後カメラや演出の処理最終処理向け

まとめ

Unityのライフサイクルは、オブジェクト生成から破棄までの一連の関数呼び出しの流れ

  • Awake():依存関係の初期化に使う
  • Start():初期状態やコンポーネント取得に使う
  • Update():プレイヤー操作やアニメーションなどフレーム単位の処理
  • FixedUpdate():物理挙動やRigidbodyの制御に使う
  • LateUpdate():カメラ追従や描画の後処理に使う

これらを正しく使い分けることで、バグの少ないわかりやすいスクリプトを書くことができます。