Unity之单例模式探索

最近在使用 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方法创建实例,原因也有迹可循,因为所有继承于它的子类都会自动创建实体.反正谁用谁知道
    • 这样的创建方法就会创建一个新的物体,并将此单例作为其类实例的引用,如果在其它地方由创建了这样一个实例,会将新创建的实例自动删除,即引用的实例不会变更
posted @ 2024-09-16 13:40  skybase  阅读(47)  评论(0)    收藏  举报