作者:王選易,出處:http://www.survivalescaperooms.com/neverdie/ 歡迎轉載,也請保留這段聲明。如果你喜歡這篇文章,請點推薦。謝謝!

該博客中的代碼均出自我的開源項目 : 迷你微信
游戲中需要單例有以下幾個原因:
在設計單例的時候,我并不建議采取延遲初始化的方案,正如云風所說:
對于單件的處理,采用靜態對象和惰性初始化的方案,簡直就是 C++ 程序員的陋習。Double Checked Locking is broken,相信很多人都讀過了。過于依賴語法糖,通常就會造成這種結果。其實讓程序有明顯的初始化和退出階段,是很容易被規劃出來的。把單件(singleton) 的處理放在正確的時機,以正確的次序來處理并非難事。
我們應該在程序某處明確定義單例是否被初始化,在初始化執行完畢后再執行正常的游戲邏輯
在Unity中,我們需要一個基類來為所有單例的操作提供統一的接口,同時,我們還要讓所有單例繼承MonoBehaviour,只有這樣才能讓單例自由使用協程這一特性。
基類設計如下,代碼鏈接
using System;using UnityEngine;namespace MiniWeChat{ [RequireComponent(typeof(GameRoot))] public class Singleton<T> : MonoBehaviour where T : Singleton<T> { PRivate static T _instance; public static T GetInstance() { return _instance; } public void SetInstance(T t) { if (_instance == null) { _instance = t; } } public virtual void Init() { return; } public virtual void Release() { return; } }}除了設計基類之外, 還需要設計一個讓所有基類初始化和銷毀的類,我們把這個類叫做GameRoot,并且把它綁定在一個名為GameRoot的GameObject上,并且把這個GameObject放在游戲進入的Main場景中。
GameRoot類設計如下,代碼鏈接
namespace MiniWeChat{ public class GameRoot : MonoBehaviour { private static GameObject _rootObj; private static List<Action> _singletonReleaseList = new List<Action>(); public void Awake() { _rootObj = gameObject; GameObject.DontDestroyOnLoad(_rootObj); StartCoroutine(InitSingletons()); } /// <summary> /// 在這里進行所有單例的銷毀 /// </summary> public void OnapplicationQuit() { for (int i = _singletonReleaseList.Count - 1; i >= 0; i--) { _singletonReleaseList[i](); } } /// <summary> /// 在這里進行所有單例的初始化 /// </summary> /// <returns></returns> private IEnumerator InitSingletons() { yield return null; // Init Singletons } private static void AddSingleton<T>() where T : Singleton<T> { if (_rootObj.GetComponent<T>() == null) { T t = _rootObj.AddComponent<T>(); t.SetInstance(t); t.Init(); _singletonReleaseList.Add(delegate() { t.Release(); }); } } public static T GetSingleton<T>() where T : Singleton<T> { T t = _rootObj.GetComponent<T>(); if (t == null) { AddSingleton<T>(); } return t; } }}有了以上兩個類之后,當我們需要新創建一個類的時候,就可以繼承Singleton<T>來創建新的單例,重寫Init和Release方法,同時在GameRoot的InitSingleton方法的適當順序執行AddSingleton<T>方法即可。具體的使用可以參考該類代碼鏈接
新聞熱點
疑難解答