最近在使用 Unity 管理远程攻击的时候涉及到了对象池,又因为需要进行脚本之间的通信,而标准通信有略显麻烦,于是使用单例的方式进行脚本之间的伪通信
-
废话不多说,首先登场的就是最为简单的单例实现方法
public class SingleBase : MonoBehaviour { public static SingleBase Instance; void Awake() => Instace = this; }
- 很明显, 首先在类的内部创建一个静态的类引用
- 接下来, 由于 Unity 中Awake()方法的实际调用在 C#脚本创建的时候,并且所有继承于 MonoBehaviour 的子类会自动创建实例,所以在Awake()方法中直接将引用赋值给 Instace
- 如何调用?
SingleBase.Instance //这样就可以直接访问该单例的所有public了
-
如果提到安全问题,无外乎公有的问题和线程安全
- 针对公有的问题,使用属性管理 get 就可以解决
- 线程安全问题,
只要在程序不动态创建单例不就解决了 dogo
-
针对非继承于 MonoBehaviour 的类,就需要考虑类的实例化的问题
这里以使用属性的方法来建立单例,其实可以不用public class SingleBase { private static SingleBase instance_pool; private SingleBase() {} public static SingleBase Instance { get { if (instance_pool == null) { instance_pool = new ObjectPool(); } return instance_pool; } }
-
如果想以 MonoBehaviour 为父类的类创建一个空对象,并在其上附加这样的单例
public class ObjectPool : MonoBehaviour { private static ObjectPool instance_pool; private ObjectPool() {} public static ObjectPool Instance { get { if (instance_pool == null) { GameObject _obj = new GameObject(); _obj.name = typeof(ObjectPool).ToString(); instance_pool = _obj.AddComponent<ObjectPool>(); } return instance_pool; } }
- 之所以不能使用new方法,是因为MonoBehaviours会抛出异常,不允许使用new方法创建实例,原因也有迹可循,因为所有继承于它的子类都会自动创建实体.
反正谁用谁知道 - 这样的创建方法就会创建一个新的物体,并将此单例作为其类实例的引用,如果在其它地方由创建了这样一个实例,会将新创建的实例自动删除,即引用的实例不会变更
- 之所以不能使用new方法,是因为MonoBehaviours会抛出异常,不允许使用new方法创建实例,原因也有迹可循,因为所有继承于它的子类都会自动创建实体.