使用 RuntimeInitializeOnLoadMethodAttribute 實現

Unity 5.2.5 開始,可以使用 RuntimeInitializeOnLoadMethodAttribute 執行繞過 MonoBehaviour 執行順序的初始化邏輯。它提供了一種建立更乾淨和強大實現的方法:

using UnityEngine;

sealed class GameDirector : MonoBehaviour
{
    // Because of using RuntimeInitializeOnLoadMethod attribute to find/create and
    // initialize the instance, this property is accessible and
    // usable even in Awake() methods.
    public static GameDirector Instance
    {
        get; private set;
    }

    // Thanks to the attribute, this method is executed before any other MonoBehaviour
    // logic in the game.
    [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
    static void OnRuntimeMethodLoad()
    {
        var instance = FindObjectOfType<GameDirector>();

        if (instance == null)
            instance = new GameObject("Game Director").AddComponent<GameDirector>();

        DontDestroyOnLoad(instance);

        Instance = instance;
    }

    // This Awake() will be called immediately after AddComponent() execution
    // in the OnRuntimeMethodLoad(). In other words, before any other MonoBehaviour's
    // in the scene will begin to initialize.
    private void Awake()
    {
        // Initialize non-MonoBehaviour logic, etc.
        Debug.Log("GameDirector.Awake()", this);
    }
}

由此產生的執行順序:

  1. GameDirector.OnRuntimeMethodLoad() 開始……
  2. GameDirector.Awake()
  3. GameDirector.OnRuntimeMethodLoad() 完成了。
  4. OtherMonoBehaviour1.Awake()
  5. OtherMonoBehaviour2.Awake()