From c850ec359c08457552d866a769b7bec2637d1da2 Mon Sep 17 00:00:00 2001 From: ALEXTANG <574809918@qq.com> Date: Thu, 20 Apr 2023 19:34:37 +0800 Subject: [PATCH] [+] SingletonSystem [+] SingletonSystem --- .../HotFix/GameBase/Singleton.meta | 3 + .../HotFix/GameBase/Singleton/TSingleton.cs | 214 ++++++++++++++++++ .../GameBase/Singleton/TSingleton.cs.meta | 3 + .../GameBase/Singleton/UnitySingleton.cs | 111 +++++++++ .../GameBase/Singleton/UnitySingleton.cs.meta | 3 + 5 files changed, 334 insertions(+) create mode 100644 Assets/GameScripts/HotFix/GameBase/Singleton.meta create mode 100644 Assets/GameScripts/HotFix/GameBase/Singleton/TSingleton.cs create mode 100644 Assets/GameScripts/HotFix/GameBase/Singleton/TSingleton.cs.meta create mode 100644 Assets/GameScripts/HotFix/GameBase/Singleton/UnitySingleton.cs create mode 100644 Assets/GameScripts/HotFix/GameBase/Singleton/UnitySingleton.cs.meta diff --git a/Assets/GameScripts/HotFix/GameBase/Singleton.meta b/Assets/GameScripts/HotFix/GameBase/Singleton.meta new file mode 100644 index 00000000..614abc11 --- /dev/null +++ b/Assets/GameScripts/HotFix/GameBase/Singleton.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 00565f0d362f4c36836804455e19c3df +timeCreated: 1681990210 \ No newline at end of file diff --git a/Assets/GameScripts/HotFix/GameBase/Singleton/TSingleton.cs b/Assets/GameScripts/HotFix/GameBase/Singleton/TSingleton.cs new file mode 100644 index 00000000..7a1f0fb0 --- /dev/null +++ b/Assets/GameScripts/HotFix/GameBase/Singleton/TSingleton.cs @@ -0,0 +1,214 @@ +using System.Collections.Generic; +using TEngine; +using UnityEngine; +using UnityEngine.SceneManagement; + +namespace GameBase +{ + /// + /// 单例接口。 + /// + public interface ISingleton + { + void Active(); + + void Release(); + } + + /// + /// 单例管理器(统一化持久和释放)。 + /// + public static class SingletonMgr + { + private static List _singletonList; + private static Dictionary _gameObjects; + private static GameObject _root; + + public static GameObject Root + { + get + { + if (_root == null) + { + _root = GameObject.Find("[SingletonMgr]"); + + if (_root == null) + { + _root = new GameObject("[SingletonMgr]") + { + transform = + { + position = Vector3.zero + } + }; + } + UnityEngine.Object.DontDestroyOnLoad(_root); + } + return _root; + } + } + + public static void Retain(ISingleton go) + { + if (_singletonList == null) + { + _singletonList = new List(); + } + + _singletonList.Add(go); + } + + public static void Retain(GameObject go) + { + if (_gameObjects == null) + { + _gameObjects = new Dictionary(); + } + + if (!_gameObjects.ContainsKey(go.name)) + { + _gameObjects.Add(go.name, go); + if (Application.isPlaying) + { + UnityEngine.Object.DontDestroyOnLoad(go); + } + } + } + + public static void Release(GameObject go) + { + if (_gameObjects != null && _gameObjects.ContainsKey(go.name)) + { + _gameObjects.Remove(go.name); + UnityEngine.Object.Destroy(go); + } + } + + public static void Release(ISingleton go) + { + if (_singletonList != null && _singletonList.Contains(go)) + { + _singletonList.Remove(go); + } + } + + public static void Release() + { + if (_gameObjects != null) + { + foreach (var item in _gameObjects) + { + UnityEngine.Object.Destroy(item.Value); + } + + _gameObjects.Clear(); + } + + if (_singletonList != null) + { + for (int i = 0; i < _singletonList.Count; ++i) + { + _singletonList[i].Release(); + } + + _singletonList.Clear(); + } + + Resources.UnloadUnusedAssets(); + } + + public static GameObject GetGameObject(string name) + { + GameObject go = null; + if (_gameObjects != null) + { + _gameObjects.TryGetValue(name, out go); + } + + return go; + } + + internal static bool ContainsKey(string name) + { + if (_gameObjects != null) + { + return _gameObjects.ContainsKey(name); + } + + return false; + } + + internal static ISingleton GetSingleton(string name) + { + for (int i = 0; i < _singletonList.Count; ++i) + { + if (_singletonList[i].ToString() == name) + { + return _singletonList[i]; + } + } + + return null; + } + + /// + /// 释放所有单例。 + /// + public static void ReStart() + { + Release(); + + SceneManager.LoadScene(0); + } + } + + /// + /// 全局单例对象(非线程安全)。 + /// + /// 泛型T。 + public abstract class TSingleton : ISingleton where T : TSingleton, new() + { + private static T _instance; + + public static T Instance + { + get + { + if (null == _instance) + { + _instance = new T(); + _instance.Init(); +#if UNITY_EDITOR + Log.Info($"TSingleton Instance:{typeof(T).Name}"); +#endif + SingletonMgr.Retain(_instance); + } + + return _instance; + } + } + + public static bool IsValid => _instance != null; + + protected TSingleton() + { + } + + protected virtual void Init() + { + } + + public virtual void Active() + { + } + + public virtual void Release() + { + if (_instance != null) + { + SingletonMgr.Release(_instance); + _instance = null; + } + } + } +} \ No newline at end of file diff --git a/Assets/GameScripts/HotFix/GameBase/Singleton/TSingleton.cs.meta b/Assets/GameScripts/HotFix/GameBase/Singleton/TSingleton.cs.meta new file mode 100644 index 00000000..70380313 --- /dev/null +++ b/Assets/GameScripts/HotFix/GameBase/Singleton/TSingleton.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: aa2cb5bb622045d7a6f2a4c4faea3ca6 +timeCreated: 1681989590 \ No newline at end of file diff --git a/Assets/GameScripts/HotFix/GameBase/Singleton/UnitySingleton.cs b/Assets/GameScripts/HotFix/GameBase/Singleton/UnitySingleton.cs new file mode 100644 index 00000000..db28b292 --- /dev/null +++ b/Assets/GameScripts/HotFix/GameBase/Singleton/UnitySingleton.cs @@ -0,0 +1,111 @@ +using TEngine; +using UnityEngine; + +namespace GameBase +{ + /// + /// 具备Unity完整生命周期的单例。 + /// + /// + public abstract class UnitySingleton : MonoBehaviour where T : MonoBehaviour + { + private static T _instance; + + public static T Instance + { + get + { + if (_instance == null) + { + var ins = UnityEngine.Object.FindObjectOfType(); + 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); + go.transform.position = Vector3.zero; + } + } + + _instance = go.GetComponent(); + if (_instance == null) + { + _instance = go.AddComponent(); + } + + 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) + { + SingletonMgr.Release(_instance.gameObject); + _instance = null; + } + } + } +} \ No newline at end of file diff --git a/Assets/GameScripts/HotFix/GameBase/Singleton/UnitySingleton.cs.meta b/Assets/GameScripts/HotFix/GameBase/Singleton/UnitySingleton.cs.meta new file mode 100644 index 00000000..c0330e3f --- /dev/null +++ b/Assets/GameScripts/HotFix/GameBase/Singleton/UnitySingleton.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 25c99243aa534df5870e36fdf9d36afd +timeCreated: 1681990223 \ No newline at end of file