Unity ライフサイクルとスクリプト有効/無効イベント総まとめ

本資料では、Unity のスクリプトが「有効/無効」状態になるタイミングと呼び出されるイベントについて整理し、分かりやすくまとめます。
「インスペクタのチェックを外す(enabled = false)状態でも呼ばれるイベント、呼ばれないイベントの一覧表」やフローチャート、そして最後にサンプルコードも掲載しています。


1. スクリプトの「有効/無効」とは?

  • スクリプトの有効/無効
    • Unity の MonoBehaviour を継承したクラスは、インスペクタのチェックボックスや enabled フラグでアクティブ/非アクティブを切り替えることができます。
    • このチェックを外した(enabled = false)状態 を「スクリプトが無効」と呼びます。
  • GameObject のアクティブ/非アクティブ
    • gameObject.SetActive(true/false) でオブジェクト自体をアクティブ/非アクティブに切り替えます。
    • GameObject 自体が非アクティブの場合、その配下のコンポーネントはすべて動作しなくなり、Awake() すら呼ばれません。

2. ライフサイクルイベントの一覧表

Unity の代表的なライフサイクルイベントと、「スクリプトが無効 (enabled = false) でも呼ばれるか」を中心にまとめた表です。

イベント名無効状態 (enabled=false) でも呼ばれるか?呼ばれるタイミング備考
Awake()はい
(※1)
コンポーネントがロードされた直後
(GameObject がアクティブの場合)
– スクリプトが無効でも一度だけ呼ばれる
– GameObject 自体が非アクティブだと呼ばれない
OnEnable()いいえスクリプトが有効化された瞬間enabled = true、またはインスペクタでチェックを入れたタイミング
Start()いいえスクリプトが初めて有効になったフレームの開始時に 1 回– 一度呼ばれると再度有効化しても再呼び出しされない(同オブジェクト内では初回のみ)
Update() / FixedUpdate() / LateUpdate()いいえ毎フレーム(または物理ステップ、描画後フレーム)– 有効な間のみ呼ばれる
OnGUI()いいえGUI イベントごとに(フレーム内で複数回呼ばれる場合あり)– 有効な間のみ呼ばれる
OnDisable()はいスクリプトが無効化される瞬間
enabled = false やインスペクタチェックを外した時)
– GameObject を非アクティブにするときにも呼ばれる
無効になる「直前」に呼ばれる
OnDestroy()はいオブジェクトやコンポーネントが破棄されるとき– 有効/無効に関係なく必ず呼ばれる
OnTriggerEnter(),
OnTriggerStay() etc.
いいえ当該トリガー(衝突)イベントが発生したタイミング– スクリプトが有効な間のみ衝突判定が処理され、コールバックが呼ばれる
OnCollisionEnter(),
OnCollisionStay() etc.
いいえ当該コリジョン(物理衝突)イベントが発生したタイミング– スクリプトが有効な間のみ衝突判定が処理され、コールバックが呼ばれる
OnMouseDown(),
OnMouseUp() etc.
いいえマウス・タッチイベントが発生したタイミング– スクリプトが有効な間のみ呼ばれる

(※1) ただし、GameObject がシーン読み込み時点で 非アクティブ (SetActive(false)) の場合は Awake() も呼ばれず、後で SetActive(true) にされたタイミングで初めて呼ばれます。


3. 有効化・無効化で呼ばれるイベントの流れ

3.1 有効化の流れ

  1. オブジェクト生成/シーン読み込み時
    • GameObject がアクティブで読み込まれるとき、Awake() が呼ばれる(スクリプトが無効でも一度は呼ばれる)。
  2. スクリプトが有効になる瞬間
    • OnEnable() が呼ばれる(enabled = true やインスペクタでチェックをオンにする)。
    • 初回であれば、次のフレーム開始時に Start() が呼ばれる(1 度だけ)。
  3. 有効な間
    • 毎フレームごとに Update() / FixedUpdate() / LateUpdate() などが呼ばれ、OnTriggerEnter()OnCollisionEnter()OnMouseDown() など各種イベントも受け付ける。

3.2 無効化の流れ

  1. スクリプトが無効化される瞬間
    • OnDisable() が呼ばれる(enabled = false やインスペクタでチェックを外す、または gameObject.SetActive(false) により間接的にスクリプトが無効扱いになる場合も同様)。
  2. 無効状態
    • Update()FixedUpdate()、衝突やマウスなどのイベントは呼ばれない。
  3. 破棄されるタイミング
    • OnDestroy() が呼ばれる(有効/無効に関係なく必ず)。

4. フローチャート(ASCII 図)

以下は、MonoBehaviour がアタッチされた GameObject がアクティブな状態でシーンに存在し、スクリプトが有効化・無効化・破棄されるまでの大まかな流れを図示したものです。

     +-----------------------------------+
     | [Awake()]                         |
     | (GameObjectがアクティブ&ロード時)   |
     +----------------+------------------+
                      |
                      v
                +------------+
                | OnEnable() | (スクリプトが有効化された)
                +------------+
                      |
                      | (初回のみ)
                      v
                +-----------+
                |  Start()  | (有効化後、最初のフレームで1回)
                +-----------+
                      |
                      v
     +-------------------------------------+
     | Update()/FixedUpdate()/LateUpdate() |
     | (スクリプトが有効な間、毎フレーム)      |
     +-------------------------------------+
                      |
                      v
            +--------------------+
            |    OnDisable()    |
            | (スクリプト無効化)  |
            +--------------------+
                      |
                      v
            +--------------------+
            |   OnDestroy()     |
            |  (破棄時に呼ばれる) |
            +--------------------+

5. よくある質問(FAQ)と注意点

  1. 「スクリプトが無効でも Awake() は呼ばれる」って本当?
    • はい、ただし GameObject がアクティブ でシーンに読み込まれた(または生成された)場合に限ります。
    • もし GameObject 自体が非アクティブなら、Awake() も呼ばれず、後で SetActive(true) になったタイミングで初めて呼ばれます。
  2. Start() は何度でも呼ばれるの?
    • いいえ、一度だけです。同一オブジェクト上で再度有効化しても、基本的に Start() は再呼び出しされません(OnEnable() は有効化のたびに呼ばれます)。
  3. 無効化したら Update() だけでなく衝突イベントなども止まるの?
    • はい。OnCollisionEnter()OnTriggerEnter()OnMouseDown() といったイベントも、スクリプトが有効な間 だけコールバックされるものです。
  4. 破棄(Destroy())されたとき、無効だと OnDestroy() は呼ばれない?
    • いいえ。無効・有効に関係なく、破棄されるときは必ず OnDestroy() が呼ばれます。リソースの解放やグローバル変数の後処理などはここで行います。

6. サンプルコード

6.1 コンソールで各イベントの呼ばれ方を確認するコード

以下のサンプルスクリプトを GameObject にアタッチし、インスペクタの有効/無効切り替えや Destroy() を試すと、各イベントが実行されたタイミングでログが出力されます。
(GameObject も含めてアクティブ/非アクティブを切り替えれば、Awake()OnEnable() の呼ばれ方も確認可能です)

using UnityEngine;

public class LifeCycleLogger : MonoBehaviour
{
    private void Awake()
    {
        Debug.Log($"[Awake] {gameObject.name} - enabled:{enabled}");
    }

    private void OnEnable()
    {
        Debug.Log($"[OnEnable] {gameObject.name} - enabled:{enabled}");
    }

    private void Start()
    {
        Debug.Log($"[Start] {gameObject.name} - enabled:{enabled}");
    }

    private void Update()
    {
        // 毎フレームの呼び出しを軽めに示したい場合はコメントアウトを外す
        // Debug.Log($"[Update] {gameObject.name} - enabled:{enabled}");
    }

    private void OnDisable()
    {
        Debug.Log($"[OnDisable] {gameObject.name} - enabled:{enabled}");
    }

    private void OnDestroy()
    {
        Debug.Log($"[OnDestroy] {gameObject.name}");
    }
}

使い方

  1. 上記スクリプトを LifeCycleLogger.cs などの名前で作成。
  2. 空の GameObject(または任意のオブジェクト)にアタッチ。
  3. 再生モード(Play)にして、インスペクタでスクリプトのチェックを外したり、GameObject をアクティブ/非アクティブに切り替えたりしてみる。
  4. コンソールにどのタイミングでメッセージが出るかを確認する。

6.2 別オブジェクトを生成&破棄する簡易サンプル

こちらは別オブジェクトの生成 → 有効/無効 → 破棄 の流れを一括でテストするためのサンプルです。

using UnityEngine;

public class TestSpawner : MonoBehaviour
{
    public GameObject prefab;

    private GameObject spawnedObject;

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Alpha1))
        {
            // プレハブからインスタンスを生成
            spawnedObject = Instantiate(prefab, Vector3.zero, Quaternion.identity);
            Debug.Log($"Spawned {spawnedObject.name}");
        }
        if (Input.GetKeyDown(KeyCode.Alpha2) && spawnedObject != null)
        {
            // スクリプトを無効化
            var script = spawnedObject.GetComponent<LifeCycleLogger>();
            if (script != null)
            {
                script.enabled = false;
                Debug.Log($"Disabled script on {spawnedObject.name}");
            }
        }
        if (Input.GetKeyDown(KeyCode.Alpha3) && spawnedObject != null)
        {
            // スクリプトを有効化
            var script = spawnedObject.GetComponent<LifeCycleLogger>();
            if (script != null)
            {
                script.enabled = true;
                Debug.Log($"Enabled script on {spawnedObject.name}");
            }
        }
        if (Input.GetKeyDown(KeyCode.Alpha4) && spawnedObject != null)
        {
            // オブジェクトを破棄
            Destroy(spawnedObject);
            Debug.Log($"Destroyed {spawnedObject.name}");
        }
    }
}

使い方

  1. LifeCycleLogger をアタッチしたプレハブ(例:MyPrefab) を用意。
  2. TestSpawner を適当なシーンのオブジェクトにアタッチし、 prefab フィールドに上記プレハブを割り当てる。
  3. プレイ中に以下のキーを押して挙動を確認する:
  • [1] → プレハブを生成 (Awake()OnEnable()Start() が順に呼ばれる)
  • [2] → スクリプトを無効化 (OnDisable() が呼ばれる)
  • [3] → スクリプトを再度有効化 (OnEnable() が呼ばれる。Start() は呼ばれない)
  • [4] → 破棄 (OnDestroy() が呼ばれる)

7. まとめ

  • 「スクリプトが無効 (enabled=false) でも呼ばれる」主なイベント
    • Awake()(GameObject がアクティブな状態でロード/生成されたとき)
    • OnDisable()(有効→無効へ切り替わる瞬間)
    • OnDestroy()(破棄時、状態問わず必ず呼ばれる)
  • 「スクリプトが無効状態では呼ばれない」イベント
    • OnEnable(), Start(), Update(), FixedUpdate(), LateUpdate(), OnGUI(), 各種衝突/マウスイベント など

今回のサンプルコードで、実際にコンソールログを確認してもらえれば、「いつどのイベントが呼ばれているか」を体感的に把握できます。
Awake() が「スクリプト無効でも一度は呼ばれる」点 と、
OnDestroy() が「最終的に必ず呼ばれる」 点は特に抑えておくと、初期化や破棄処理でのトラブルを防ぐことができます。

以上、「Unity ライフサイクルとスクリプト有効/無効イベント総まとめ」でした。ぜひ開発時の参考にしてみてください。

Unity

Posted by hidepon