什么是单例?
一个类有且仅有一个实例,它自行实例化并向整个系统提供这个实例。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()); } }