Unity之单例模式基类

最近在学习Unity程序框架,于是我来记录一下单例模式基类


单例模式基类是什么?就是通过写一个基类脚本、再用其他脚本继承基类脚本实现功能的一种方式,下面是一个简单的基类脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BassManager<T> where T:class,new()
{
private static T instance;
//注意这里我们没有私有化构造函数,其实是不必要的,你知道我们在用单例模式就不会new一个实例了。
public static T Instance
{
get
{
if(instance == null)
instance = new T();
return instance;
}
}
}

接下来我们写的脚本,只需要继承这个单例模式基类,比如:

1
2
3
4
5
6
7
8
9
10
11
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Test: BassManager<Test>
{
public void Speak()
{
Debug.Log("我调用了方法");
}
}

之后我们在使用Test脚本想调用方法、又不想创建新实例(用单例模式)时,就只需要Test.Instance().Speak()
潜在的问题,是多线程


此外还写了两种单例模式基类,一类是继承MonoBehaviour的,一类是没继承的。
这里我稍微解释一下关于“lock”和“自动式挂载”的问题。首先是lock锁,lock锁的存在是为了解决多线程访问的问题。

我的建议是,继承Mono的脚本就不用加lock了,因为Unity给我们制定好了规则,不会出现多线程访问的问题;不继承Mono的脚本就加上lock。

关于“自动式挂载”,你可能见到,有的继承了Mono的代码写法和我不一样,它们会多出一个Awake方法。我感觉我的代码更好一些,因为会自动挂载脚本,大家辩证看待、互相学习就好。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class SingleMono<T> : MonoBehaviour where T : MonoBehaviour
{
//这个是继承MonoBehaviour的
private static T instance;
public static T Instance()
{
if(instance == null)
{
GameObject go = new GameObject(typeof(T).ToString());
//过场景不移除
DontDestroyOnLoad(go);
instance = go.AddComponent<T>();
}
return instance;
}
}

没继承的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class SingletonBase<T> where T : class, new()
{
private static T instance;
protected static readonly object _lock = new object();
public static T GetInstance()
{
if (instance == null)
{
lock(_lock)
{
if (instance == null)
{
instance = new T();
}
}
}
return instance;

}
}