作者:王選易,出處:http://m.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>方法即可。具體的使用可以參考該類代碼鏈接
新聞熱點
疑難解答