游戏设计模式----单例模式
Posted _不动明王
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了游戏设计模式----单例模式相关的知识,希望对你有一定的参考价值。
定义
单例模式是指在内存中只会创建且仅创建一次对象的设计模式。在程序中多次使用同一个对象且作用相同时,为了防止频繁地创建对象使得内存飙升,单例模式可以让程序仅在内存中创建一个对象,让所有需要调用的地方都共享这一单例对象。
C#
单例模式主要分两种
饿汉式
在类加载时已经创建好该单例对象。
public class Test_Instan
private static Test_Instan instant=new Test_Instan();
public static Test_Instan Instant
get
return instant;
private Test_Instan()
懒汉式
在真正需要使用对象时才去创建该单例类对象
public class Test_Instan
private static Test_Instan instant;
public static Test_Instan Instant
get
if (instant==null)
instant = new Test_Instan();
return instant;
private Test_Instan()
不足之处:如果两个线程同时判断instant为空那么它们都会去实例化一个Test_Instan对象,这就变成双例了。
改进:利用锁
public class Test_Instan
private Test_Instan()
private static Test_Instan instant;
private static object syncRoot = new object();
public static Test_Instan Instant
get
if (instant == null) // 假如线程A和线程B同时看到instant为null
lock (syncRoot)//线程A或者线程B获得该锁进行初始化,另一线程阻塞
if (instant == null)//其中一个线程进入该分支创建单例对象,另外一个阻塞线程,阻塞结束后进入该分支则会发现instant已被创建
instant = new Test_Instan();
return instant;
Unity的单例
饿汉式
类似与我们上面的饿汉式,不过这里要注意的是Awake函数的执行顺序是不可控的,通俗来说每次运行程序的时候每个脚本的执行顺序都不一样,通常我们会自己写一个初始函数函数,来控制我们的执行循序,确保单例的初始化在所有的逻辑之上。
public class SingletonUnity : MonoBehaviour
private static SingletonUnity instant;
public static SingletonUnity Instant
get
return instant;
private void Awake()
instant = this;
懒汉式
由于unity的所有继承自MonoBehaviour的脚本都必须挂在一个游戏对象上,否则无法执行,也谈不上用new来实例化,这点我们要尤为注意。
public class SingletonUnity : MonoBehaviour
private static SingletonUnity instant;
public static SingletonUnity Instant
get
if (instant==null)
instant= FindObjectOfType<SingletonUnity>();
if (instant==null)
GameObject instan_ = new GameObject();
instant = instan_.AddComponent<SingletonUnity>();
return instant;
问题
对比我们上面纯C#的写法,在Unity创建的MonoBehaviour类的单例并没有对MonoBehaviour类的实例化进行非公有化,因为,在Unity中,MonoBehaviour类有可视化操作的特点,当我们手动拖拽多个单例脚本到游戏中,这时我们运行程序很可能会出现逻辑错误,我们单例模式的原则或者说目的是保证一个类只有一个实例,所以我们需要改进一下。
public class SingletonUnity : MonoBehaviour
private static SingletonUnity instant;
public static SingletonUnity Instant
get
if (instant == null)
SingletonUnity[] instants = FindObjectsOfType<SingletonUnity>();
for (int i = 0; i < instants.Length; i++)
Destroy(instants[i].gameObject);
GameObject instan_ = new GameObject();
instant = instan_.AddComponent<SingletonUnity>();
return instant;
最后写个测试脚本测试下
public class Client_sigle : MonoBehaviour
void Start()
Debug.Log(SingletonUnity.Instant.name);
运行前
运行后
当然,你也可以按自己的需求,更改上面写法。
改进:上面单例的写法代码量比较多,当游戏中有多个单例,显然不可能用我们的复制粘贴,这时我们可以用泛型来增强我们的复用性。
public class SingletonUnity<T> : MonoBehaviour where T: MonoBehaviour
private static T instant;
public static T Instant
get
if (instant == null)
T[] instants = FindObjectsOfType<T>();
for (int i = 0; i < instants.Length; i++)
Destroy(instants[i].gameObject);
GameObject instan_ = new GameObject();
instant = instan_.AddComponent<T>();
return instant;
只需要让单例继承该类即可。
以上是关于游戏设计模式----单例模式的主要内容,如果未能解决你的问题,请参考以下文章