单例模式在游戏开发中会经常用到,特别是对于那种用于管理对象的地方,采用单例模式来实现会非常方便。下面先贴上一段在Unity中实现单例模式的代码【该代码转自网上】。
using UnityEngine;
using System.Collections;
public class Singleton<T> : MonoBehaviour where T : MonoBehaviour
{
private static T _instance;
private static object _lock = new object();
private static bool applicationIsQuitting = false;
public static T Instance
{
get
{
if (applicationIsQuitting)
{
return null;
}
lock (_lock)
{
if (_instance == null)
{
_instance = (T)FindObjectOfType(typeof(T));
if (FindObjectsOfType(typeof(T)).Length > 1)
{
return _instance;
}
if (_instance == null)
{
GameObject singleton = new GameObject();
_instance = singleton.AddComponent<T>();
singleton.name = "(singleton)" + typeof(T).ToString();
DontDestroyOnLoad(singleton);
}
}
return _instance;
}
}
}
public void OnDestroy()
{
applicationIsQuitting = true;
}
}
这段代码实现单例模式的方式是常规的写法,只是再Unity的应用中,代码在判断该单例未实例化时会先生成一个GameObject并附加该脚本。运行时的效果如下。
其中,那个(singleton)HeroManager就是利用单例模式实例化出来的。然后单例模式中的坑就在这里。就以这个英雄管理器为例,假如我有A,B两个场景,在B场景中有个预先人为创建的GameObject,并绑定了HeroManager这个脚本。如图:
如果在A场景中,我们有个地方事先调用了HeroManager.Instance中的一个方法,亦或是对其中的一个公有变量进行了修改,程序并不会报错,在调用HeroManager.Instance的时候单利模式的设计会自动创建一个(singleton)HeroManager出来,然后在切换到B场景的时候,其实这时候内存中就会存在两份HeroManger,这时候如果代码调用HeroManager.Instance则会出现不明确的错误,如果试图去调用其中的某个对象,很有可能会抛出“unassignedreferenceexception”,这个异常就是由于同个脚本绑定了多次对象而引起的。所以在使用单例模式的时候,如果该脚本在某些地方是手动绑定的,那么在之前部分一定不要去人为调用过,不然就会掉入这个大坑。