使用 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()