国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

【Unity3D基礎教程】給初學者看的Unity教程(七):在Unity中構建健壯的單例模式(Singleton)

2019-11-17 02:24:16
字體:
來源:轉載
供稿:網友

【Unity3D基礎教程】給初學者看的Unity教程(七):在Unity中構建健壯的單例模式(Singleton)

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

hh

該博客中的代碼均出自我的開源項目 : 迷你微信

為什么需要單例模式

游戲中需要單例有以下幾個原因:

  • 我們需要在游戲開始前和結束前做一些操作,比如網絡的鏈接和斷開,資源的加載和卸載,我們一般會把這部分邏輯放在單例里。
  • 單例可以控制初始化和銷毀順序,而靜態變量和場景中的GameObject都無法控制自己的創建和銷毀順序,這樣就會造成很多潛在的問題。
  • Unity3D的GameObject需要動態創建。而不是固定在場景里,我們需要使用單例來創建GameObject。
  • Unity3D的場景中的各個GameObject需要從單例中存取數據。

單例的設計原則

在設計單例的時候,我并不建議采取延遲初始化的方案,正如云風所說:

對于單件的處理,采用靜態對象和惰性初始化的方案,簡直就是 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>方法即可。具體的使用可以參考該類代碼鏈接


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 苗栗市| 淮阳县| 栖霞市| 永顺县| 丹棱县| 克什克腾旗| 马边| 广东省| 嘉黎县| 孙吴县| 丽江市| 普洱| 观塘区| 佛教| 新宾| 新疆| 乐安县| 洱源县| 大洼县| 子长县| 沙洋县| 武定县| 宁阳县| 南和县| 崇左市| 和顺县| 延津县| 从江县| 东乌| 咸宁市| 明溪县| 常德市| 易门县| 中山市| 临清市| 饶平县| 江孜县| 招远市| 茌平县| 宜春市| 云阳县|