Unity中單例的寫法

什麼是單例?
一個類有且僅有一個實例,它自行實例化並向整個系統提供這個實例。segmentfault

做爲最簡單的設計模式之一,單例模式常常會被使用,但Unity中的寫法與其餘開發環境下有所不一樣。
要在Unity中保持一個單例,又要很方便的調用MonoBehaviour對象不報錯,要對寫法進行改造。
先上單例基類代碼:MonoSingleton.cs設計模式

using UnityEngine;

/// <summary>
/// MonoBehaviour單例基類<br/>
/// <para>ZhangYu 2018-03-14</para>
/// <para>Blog:https://segmentfault.com/a/1190000015261387</para>
/// </summary>
public class MonoSingleton<T> : MonoBehaviour where T : MonoBehaviour {

    // 單例
    private static T instance;

    /// <summary>獲取單例</summary>
    public static T GetInstance() {
        if (instance == null) {
            // 在已存在的腳本中查找單例
            instance = (T)FindObjectOfType(typeof(T));

            // 建立單例
            if (instance == null) new GameObject(typeof(T).Name).AddComponent<T>();
        }
        return instance;
    }

    // 獲取單例/銷燬重複對象
    protected virtual void Awake() {
        if (instance == null) {
            instance = this as T;
            DontDestroyOnLoad(gameObject);
            Init();
        } else if (instance != this) {
            if (instance.gameObject != gameObject) {
                Destroy(gameObject);
            } else {
                Destroy(this);
            }
        }
    }

    // 重空單例
    protected virtual void OnDestroy() {
        if (instance == this) instance = null;
    }

    // 初始化
    protected virtual void Init() {

    }

}

用法:
自定義的單例繼承Singleton並傳入本身的類型。
例如:GameManager.cside

using UnityEngine;

public class GameManager : Singleton<GameManager> {

    protected override void Init() {
        // 在這裏寫本身的代碼
    }

}

狀況1:當場景中已經存在一個GameManager,其餘後出現的GameManager對象都會被銷燬,保證系統中有且僅有一個實例。測試

狀況2:當場景中無GameMananger時,會建立一個叫GameMananger的物體並附加腳本,自行實例化。
測試代碼:Test.csthis

using UnityEngine;

public class Test : MonoBehaviour {

    private void Start () {
        print(GameManager.getInstance());
    }
    
}

運行結果
自行實例化

相關文章
相關標籤/搜索