浅谈单例模式在游戏开发中的应用

前言

如果在外部想在不同的时间结点、不同的位置访问某类中的成员且想要保持访问时,成员地址唯一。
那么可以考虑将该类声明为静态类,但若是成员中包含公共的数据类型,此时便可以考虑将该类做成一个单例

单例模式

由于类中的数据,必须在实例化后堆栈才会为其分配变量的值,以及引用类型的地址,通过地址在静态存储区中也可访问其值。
那么,脚本文件每初始化一次,不管数据相不相同,已经是两个对象了,那么需要读取或者更新的字段就有可能出错。
所以,要保证外界可访问自身
需要在给类一个静态的公共自身成员,作为访问的中间桥梁

private static T _instance;
public static T Instance => GetInstance();

要保证,单一对象

  • 在第一次访问时,new()
  • 如果已经实例化,使用之前实例化过的对象
 private static T GetInstance()
 {
    if (_instance != null) return _instance;
    _instance = new T();
    _instance.Initialize();
    return _instance;
 }
        
public static void CreateSingleton()
{
    GetInstance();
}

访问时:SingletonAClass.Instance.Function();
就可以访问到唯一的function方法了。

单例类

实际在开发中,会根据需求做成单例类的形式,使用不同的泛型约束,构造成不同的基类。
使用时,根据需求继承即可。

不继承Monobehavior的形式

在做一些公共数据库的时候,游戏频繁访问的一些实时数据,一般会把它做成单例,然后根据需求给数据一些 get set方法。

 /// 
    /// 通用单例。
    /// 
    /// 泛型T。
    public abstract class Singleton<T> where T : Singleton<T>, new()
    {
        private static T _instance;
        public static T Instance => GetInstance();

        private static T GetInstance()
        {
            if (_instance != null) return _instance;
            _instance = new T();
            _instance.Initialize();
            return _instance;
        }
        
        public static void CreateSingleton()
        {
            GetInstance();
        }

        public static bool HasInstance()
        {
            return _instance != null;
        }

        public static void DestroySingleton()
        {
            _instance?.UnInitialize();
            _instance = null;
        }

        protected abstract void Initialize();
        protected abstract void UnInitialize();
    }

继承自Monobehavior的形式

最常见的,流程管理、总控的XXManager、XXController的脚本,一般会频繁调用,没有必要每次都实例化一个新的对象,实际会做成单例。约束绑定继承自Monobehavior

/// 
    /// 具备Unity完整生命周期的单例。
    /// 
    /// 
    public abstract class UnitySingleton<T> : MonoBehaviour where T : MonoBehaviour
    {
        private static T _instance;

        public static T Instance
        {
            get
            {
                if (_instance == null)
                {
                    var ins = FindObjectOfType<T>();
                    if (ins != null)
                    {
                        var obj = ins.gameObject;
                        obj.name = typeof(T).Name;
                        _instance = ins;
                        SingletonMgr.Retain(obj);
                        return Instance;
                    }

                    System.Type thisType = typeof(T);
                    string instName = thisType.Name;
                    GameObject go = SingletonMgr.GetGameObject(instName);
                    if (go == null)
                    {
                        go = GameObject.Find($"[{instName}]");
                        if (go == null)
                        {
                            go = new GameObject($"[{instName}]")
                            {
                                transform =
                                {
                                    position = Vector3.zero
                                }
                            };
                        }
                    }

                    _instance = go.GetComponent<T>();
                    if (_instance == null)
                    {
                        _instance = go.AddComponent<T>();
                    }

                    if (_instance == null)
                    {
                        Log.Error($"Can't create UnitySingleton<{typeof(T)}>");
                    }
                }

                return _instance;
            }
        }

        public static T Active()
        {
            return Instance;
        }

        public static bool IsValid => _instance != null;

        private bool CheckInstance()
        {
            if (this == Instance)
            {
                return true;
            }

            GameObject.Destroy(gameObject);
            return false;
        }

        protected virtual void OnLoad()
        {
        }

        public virtual void Awake()
        {
            if (CheckInstance())
            {
                OnLoad();
            }
#if UNITY_EDITOR
            Log.Debug($"UnitySingleton Instance:{typeof(T).Name}");
#endif
            GameObject tEngine = SingletonMgr.Root;
            if (tEngine != null)
            {
                this.gameObject.transform.SetParent(tEngine.transform);
            }
        }

        protected virtual void OnDestroy()
        {
            Release();
        }

        public static void Release()
        {
            if (_instance == null) return;
            SingletonMgr.Release(_instance.gameObject);
            _instance = null;
        }
    }

你可能感兴趣的:(单例模式)