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

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

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

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

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

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


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 泾川县| 南陵县| 汉阴县| 贞丰县| 淄博市| 芦山县| 满城县| 渑池县| 水富县| 长海县| 石门县| 平南县| 台湾省| 莱芜市| 泰宁县| 富阳市| 库伦旗| 南召县| 乐都县| 咸宁市| 通辽市| 成武县| 吉木乃县| 安康市| 定陶县| 桑日县| 清徐县| 滁州市| 巴彦淖尔市| 邓州市| 南陵县| 通河县| 射阳县| 许昌市| 阳东县| 靖安县| 孝昌县| 正安县| 上虞市| 齐齐哈尔市| 白水县|