什麼是單例?
一個類有且僅有一個實例,它自行實例化並向整個系統提供這個實例。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()); } }