Unity3d中C#单例模式实现
为什么要使⽤单例模式
在我们的整个游戏⽣命周期当中,有很多对象从始⾄终有且只有⼀个。这个唯⼀的实例只需要⽣成⼀次,并且直到游戏结束才需要销毁。 单例模式⼀般应⽤于管理器类,或者是⼀些需要持久化存在的对象。
Unity3d中单例模式的实现⽅式
(⼀)c#当中实现单例模式的⽅法
因为单例本⾝的写法不是重点,所以这⾥就略过,直接上代码。
以下代码来⾃于MSDN。
[csharp]
1. public sealed class Singleton
2. {
3.    private static volatile Singleton instance;
4.    private static object syncRoot = new Object();
5.    public static Singleton Instance
6.    {
7.      get
8.      {
9.          if (instance == null)
10.          {
11.            lock (syncRoot)
12.            {
13.                if (instance == null)
14.                  instance = new Singleton();
15.            }
16.          }
17.          return instance;
18.      }
19.    }
20. }
public sealed class Singleton
{
private static volatile Singleton instance;
private static object syncRoot = new Object();
public static Singleton Instance
{
get
{
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)
instance = new Singleton();
}
}
return instance;
}
}
}
以上代码是⽐较完整版本的c#单例。在unity当中,如果不需要使⽤到monobeheviour的话,可以使⽤这种⽅式来构建单例。
(⼆)如果是MonoBeheviour呢?
MonoBeheviour和⼀般的类有⼏个重要区别,体现在单例模式上有两点。
第⼀,MonoBehaviour不能使⽤构造函数进⾏实例化,只能挂载在GameObject上。
第⼆,当切换场景时,当前场景中的GameObject都会被销毁(LoadLevel带有additional参数时除外),这种情况下,我们的单例对象也会被销毁。
为了使之不被销毁,我们需要进⾏DontDestroyOnLoad的处理。同时,为了保持场景当中只有⼀个实例,我们要对当前场景中的单例进⾏判断,如果存在其他的实例,则应该将其全部删除。
因此,构建单例的⽅式会变成这样。
[csharp]
1. public sealed class SingletonMoBehaviour: MonoBehaviour
2. {
3.    private static volatile SingletonBehaviour instance;
4.    private static object syncRoot = new Object();
5.    public static SingletonBehaviour Instance
6.    {
7.        get
8.        {
9.            if (instance == null)
10.            {
11.                lock (syncRoot)
12.                {
13.                    if (instance == null)  {
14.                        SingletonBehaviour[] instances = FindObjectsOfType<SingletonBehaviour>();
15.                        if (instances != null){
16.                            for (var i = 0; i < instances.Length; i++) {
17.                                Destroy(instances[i].gameObject);
18.                            }
19.                        }
20.                        GameObject go = new GameObject(“_SingletonBehaviour”);
21.                        instance = go.AddComponent<SingletonBehaviour>();
22.                        DontDestroyOnLoad(go);
23.                    }
24.                }
25.            }
26.            return instance;
27.        }
28.    }
29. }
public sealed class SingletonMoBehaviour: MonoBehaviour
{
private static volatile SingletonBehaviour instance;
private static object syncRoot = new Object();
public static SingletonBehaviour Instance
{
get
{
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)  {
SingletonBehaviour[] instances = FindObjectsOfType<SingletonBehaviour>();
if (instances != null){
for (var i = 0; i < instances.Length; i++) {
Destroy(instances[i].gameObject);
}
}
GameObject go = new GameObject("_SingletonBehaviour");
instance = go.AddComponent<SingletonBehaviour>();
DontDestroyOnLoad(go);
}
}
}
return instance;
}
}
}
这种⽅式并⾮完美。其缺陷⾄少有:
* 如果有许多的单例类,会需要复制粘贴这些代码
* 有些时候我们也许会希望使⽤当前存在的所有实例,⽽不是删除全部新建⼀个实例。(这个未必是缺陷,只是设计的不同)
在本⽂后⾯将会附上这种单例模式的代码以及。
(三)使⽤模板类实现单例
为了避免重复代码,我们可以使⽤模板类的⽅式来⽣成单例。⾮MonoBehaviour的实现⽅式这⾥就不赘述,只说monoBehaviour的。 代码
单例模式的几种实现方式[csharp]
1. public sealed class SingletonTemplate<T> : MonoBehaviour where T : MonoBehaviour
2. {
3.    private static volatile T instance;
4.    private static object syncRoot = new Object();
5.    public static T Instance
6.    {
7.        get
8.        {
9.            if (instance == null)
10.            {
11.                lock (syncRoot)
12.                {
13.                    if (instance == null)
14.                    {
15.                        T[] instances = FindObjectsOfType<T>();
16.                        if (instances != null)
17.                        {
18.                            for (var i = 0; i < instances.Length; i++)
19.                            {
20.                                Destroy(instances[i].gameObject);
21.                            }
22.                        }
23.                        GameObject go = new GameObject();
24.                        go.name = typeof(T).Name;
25.                        instance = go.AddComponent<T>();
26.                        DontDestroyOnLoad(go);
27.                    }
28.                }
29.            }
30.            return instance;
31.        }
32.    }
33. }

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。