【Unity】PrefabをInstantiateした時のStartとAwakeいつ実行される?

はじめに

Unityでは用意しておいたPrefabをInstatinateしてゲーム上に反映するということがしばしばあると思います。

その際のAwakeとStartの挙動について知っておいた方がよさそうな感じだったので、記事に残しておきます。

サンプル

以下のようにComponentAクラスを作成し、これをアタッチしたPrefabAがあると仮定します。


public class ComponentA : MonoBehaviour
{
    public void Initialize()
    {
        Debug.Log("Initializeが呼ばれた");
    }

    void Awake()
    {
        Debug.Log("Awakeが呼ばれた");
    }

    void Start()
    {
        Debug.Log("Startが呼ばれた");
    }
}

PrefabAはExampleクラスから参照され下記のようにInstatinateを行います。

public class Example : MonoBehaviour
{
    public GameObject PrefabA;

    void Start()
    {
        var obj = Instantiate(PrefabA, transform);
        var prefabA = obj.GetComponent<ComponentA>();
        prefabA.Initialize();
    }
}

このとき実行順としては以下のようになります。

var obj = Instantiate(PrefabA, transform);      // 1. オブジェクト生成 → Awake実行
var prefabA = obj.GetComponent<ComponentA>();    // 2. ComponentAの取得
prefabA.Initialize();                            // 3. Initializeの呼び出し
// 4. 次のフレーム開始前にComponentAのStartが実行される

上記のような感じでComponentAのStartはInstatinate直後ではなく次のフレームの先頭で呼ばれる形になります。

なのでStartで参照を設定してInitializeで初期化のような書き方をしているとNull参照でエラーになり、正しく初期化されないので注意が必要です。(まさにそうなりました)

さいごに

Unityでスクリプトを作成したときにデフォルトで記述されるのはStartですが、Startは上記のように実行タイミングが遅い場合があるので、基本的にはAwakeに書くのがよさそうな気がしています。

複数種類のComponentがあってComponentAの後にComponentBの初期化をしたい、とかがあればAwake、Startを使い分けてもいいかもですが、それもExecute Orderで制御できますし、StartとAwakeは元々どういう用途を想定しているのですかね?

短めですが、以上となります。
お読みいただきありがとうございます。

コメント

タイトルとURLをコピーしました