From f9f9122027923cdc554e4c7b2c2e49cb8fd9ce60 Mon Sep 17 00:00:00 2001
From: ALEXTANG <574809918@qq.com>
Date: Mon, 13 May 2024 14:09:32 +0800
Subject: [PATCH] =?UTF-8?q?=E5=8D=95=E4=BE=8B=E7=B3=BB=E7=BB=9F=E5=AE=8C?=
=?UTF-8?q?=E5=96=84=E7=94=9F=E5=91=BD=E5=91=A8=E6=9C=9F=E3=80=81=E6=94=AF?=
=?UTF-8?q?=E6=8C=81Dispose?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../GameScripts/HotFix/GameBase/Singleton.cs | 44 +++++-
.../HotFix/GameBase/SingletonBehaviour.cs | 108 ++++++++++++++
.../GameBase/SingletonBehaviour.cs.meta | 3 +
.../HotFix/GameBase/SingletonSystem.cs | 141 ++++++++++++++++++
.../HotFix/GameBase/SingletonSystem.cs.meta | 3 +
.../GameScripts/HotFix/GameLogic/GameApp.cs | 5 +-
.../GameLogic/GameApp_RegisterSystem.cs | 2 +-
7 files changed, 297 insertions(+), 9 deletions(-)
create mode 100644 UnityProject/Assets/GameScripts/HotFix/GameBase/SingletonBehaviour.cs
create mode 100644 UnityProject/Assets/GameScripts/HotFix/GameBase/SingletonBehaviour.cs.meta
create mode 100644 UnityProject/Assets/GameScripts/HotFix/GameBase/SingletonSystem.cs
create mode 100644 UnityProject/Assets/GameScripts/HotFix/GameBase/SingletonSystem.cs.meta
diff --git a/UnityProject/Assets/GameScripts/HotFix/GameBase/Singleton.cs b/UnityProject/Assets/GameScripts/HotFix/GameBase/Singleton.cs
index 2f14742f..18be3b73 100644
--- a/UnityProject/Assets/GameScripts/HotFix/GameBase/Singleton.cs
+++ b/UnityProject/Assets/GameScripts/HotFix/GameBase/Singleton.cs
@@ -1,14 +1,14 @@
-using TEngine;
+using System.Diagnostics;
namespace GameBase
{
///
- /// 通用单例。
+ /// 全局对象必须继承于此。
///
- /// 泛型T。
- public class Singleton where T : new()
+ /// 子类类型。
+ public abstract class Singleton : ISingleton where T : Singleton, new()
{
- private static T _instance;
+ protected static T _instance = default(T);
public static T Instance
{
@@ -17,11 +17,43 @@ namespace GameBase
if (null == _instance)
{
_instance = new T();
- Log.Assert(_instance != null);
+ _instance.Init();
+ SingletonSystem.Retain(_instance);
}
return _instance;
}
}
+
+ public static bool IsValid => _instance != null;
+
+ protected Singleton()
+ {
+#if UNITY_EDITOR
+ string st = new StackTrace().ToString();
+ // using const string to compare simply
+ if (!st.Contains("GameBase.Singleton`1[T].get_Instance"))
+ {
+ UnityEngine.Debug.LogError($"请必须通过Instance方法来实例化{typeof(T).FullName}类");
+ }
+#endif
+ }
+
+ protected virtual void Init()
+ {
+ }
+
+ public virtual void Active()
+ {
+ }
+
+ public virtual void Release()
+ {
+ if (_instance != null)
+ {
+ SingletonSystem.Release(_instance);
+ _instance = null;
+ }
+ }
}
}
\ No newline at end of file
diff --git a/UnityProject/Assets/GameScripts/HotFix/GameBase/SingletonBehaviour.cs b/UnityProject/Assets/GameScripts/HotFix/GameBase/SingletonBehaviour.cs
new file mode 100644
index 00000000..91010dbc
--- /dev/null
+++ b/UnityProject/Assets/GameScripts/HotFix/GameBase/SingletonBehaviour.cs
@@ -0,0 +1,108 @@
+using TEngine;
+using UnityEngine;
+
+namespace GameBase
+{
+ ///
+ /// 全局MonoBehavior必须继承于此
+ ///
+ /// 子类类型
+ public class SingletonBehaviour : MonoBehaviour where T : SingletonBehaviour
+ {
+ private static T _instance;
+
+ private void Awake()
+ {
+ if (CheckInstance())
+ {
+ OnLoad();
+ }
+ }
+
+ private bool CheckInstance()
+ {
+ if (this == Instance)
+ {
+ return true;
+ }
+ Object.Destroy(gameObject);
+ return false;
+ }
+
+ protected virtual void OnLoad()
+ {
+
+ }
+
+ protected virtual void OnDestroy()
+ {
+ Release();
+ }
+
+ ///
+ /// 判断对象是否有效
+ ///
+ public static bool IsValid
+ {
+ get
+ {
+ return _instance != null;
+ }
+ }
+
+ public static T Active()
+ {
+ return Instance;
+ }
+
+ public static void Release()
+ {
+ if (_instance != null)
+ {
+ SingletonSystem.Release(_instance.gameObject);
+ _instance = null;
+ }
+ }
+
+ ///
+ /// 实例
+ ///
+ public static T Instance
+ {
+ get
+ {
+ if (_instance == null)
+ {
+ System.Type thisType = typeof(T);
+ string instName = thisType.Name;
+ GameObject go = SingletonSystem.GetGameObject(instName);
+ if (go == null)
+ {
+ go = GameObject.Find($"/{instName}");
+ if (go == null)
+ {
+ go = new GameObject(instName);
+ go.transform.position = Vector3.zero;
+ }
+ SingletonSystem.Retain(go);
+ }
+
+ if (go != null)
+ {
+ _instance = go.GetComponent();
+ if (_instance == null)
+ {
+ _instance = go.AddComponent();
+ }
+ }
+
+ if(_instance == null)
+ {
+ Log.Error($"Can't create SingletonBehaviour<{typeof(T)}>");
+ }
+ }
+ return _instance;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/UnityProject/Assets/GameScripts/HotFix/GameBase/SingletonBehaviour.cs.meta b/UnityProject/Assets/GameScripts/HotFix/GameBase/SingletonBehaviour.cs.meta
new file mode 100644
index 00000000..5534933a
--- /dev/null
+++ b/UnityProject/Assets/GameScripts/HotFix/GameBase/SingletonBehaviour.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: bc365e281d234e61891bf9f922a0897a
+timeCreated: 1715574965
\ No newline at end of file
diff --git a/UnityProject/Assets/GameScripts/HotFix/GameBase/SingletonSystem.cs b/UnityProject/Assets/GameScripts/HotFix/GameBase/SingletonSystem.cs
new file mode 100644
index 00000000..99bde03c
--- /dev/null
+++ b/UnityProject/Assets/GameScripts/HotFix/GameBase/SingletonSystem.cs
@@ -0,0 +1,141 @@
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.SceneManagement;
+
+namespace GameBase
+{
+ public interface ISingleton
+ {
+ ///
+ /// 激活接口,通常用于在某个时机手动实例化
+ ///
+ void Active();
+
+ ///
+ /// 释放接口
+ ///
+ void Release();
+ }
+
+ ///
+ /// 框架中的全局对象与Unity场景依赖相关的DontDestroyOnLoad需要统一管理,方便重启游戏时清除工作
+ ///
+ public static class SingletonSystem
+ {
+ private static List _singletons;
+ private static Dictionary _gameObjects;
+
+ public static void Retain(ISingleton go)
+ {
+ if (_singletons == null)
+ {
+ _singletons = new List();
+ }
+
+ _singletons.Add(go);
+ }
+
+ public static void Retain(GameObject go)
+ {
+ if (_gameObjects == null)
+ {
+ _gameObjects = new Dictionary();
+ }
+
+ if (_gameObjects.TryAdd(go.name, go))
+ {
+ if (Application.isPlaying)
+ {
+ Object.DontDestroyOnLoad(go);
+ }
+ }
+ }
+
+ public static void Release(GameObject go)
+ {
+ if (_gameObjects != null && _gameObjects.ContainsKey(go.name))
+ {
+ _gameObjects.Remove(go.name);
+ Object.Destroy(go);
+ }
+ }
+
+ public static void Release(ISingleton go)
+ {
+ if (_singletons != null && _singletons.Contains(go))
+ {
+ _singletons.Remove(go);
+ }
+ }
+
+ public static void Release()
+ {
+ if (_gameObjects != null)
+ {
+ foreach (var item in _gameObjects)
+ {
+ Object.Destroy(item.Value);
+ }
+
+ _gameObjects.Clear();
+ }
+
+ if (_singletons != null)
+ {
+ for (int i = 0; i < _singletons.Count; ++i)
+ {
+ _singletons[i].Release();
+ }
+
+ _singletons.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;
+ }
+
+ public static void Restart()
+ {
+ if (Camera.main != null)
+ {
+ Camera.main.gameObject.SetActive(false);
+ }
+
+ Release();
+ SceneManager.LoadScene(0);
+ }
+
+ internal static ISingleton GetSingleton(string name)
+ {
+ for (int i = 0; i < _singletons.Count; ++i)
+ {
+ if (_singletons[i].ToString() == name)
+ {
+ return _singletons[i];
+ }
+ }
+
+ return null;
+ }
+ }
+}
\ No newline at end of file
diff --git a/UnityProject/Assets/GameScripts/HotFix/GameBase/SingletonSystem.cs.meta b/UnityProject/Assets/GameScripts/HotFix/GameBase/SingletonSystem.cs.meta
new file mode 100644
index 00000000..21fcf5b1
--- /dev/null
+++ b/UnityProject/Assets/GameScripts/HotFix/GameBase/SingletonSystem.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 4ad00b596d0743a4b04591fe52087d0f
+timeCreated: 1715574577
\ No newline at end of file
diff --git a/UnityProject/Assets/GameScripts/HotFix/GameLogic/GameApp.cs b/UnityProject/Assets/GameScripts/HotFix/GameLogic/GameApp.cs
index f5707b3b..0f3bd97e 100644
--- a/UnityProject/Assets/GameScripts/HotFix/GameLogic/GameApp.cs
+++ b/UnityProject/Assets/GameScripts/HotFix/GameLogic/GameApp.cs
@@ -19,7 +19,7 @@ public partial class GameApp:Singleton
_hotfixAssembly = (List)objects[0];
Log.Warning("======= 看到此条日志代表你成功运行了热更新代码 =======");
Log.Warning("======= Entrance GameApp =======");
- Instance.Init();
+ Instance.Active();
Instance.Start();
Utility.Unity.AddUpdateListener(Instance.Update);
Utility.Unity.AddFixedUpdateListener(Instance.FixedUpdate);
@@ -60,8 +60,9 @@ public partial class GameApp:Singleton
Utility.Unity.RemoveDestroyListener(Instance.OnDestroy);
Utility.Unity.RemoveOnDrawGizmosListener(Instance.OnDrawGizmos);
Utility.Unity.RemoveOnApplicationPauseListener(Instance.OnApplicationPause);
- return;
}
+
+ SingletonSystem.Release();
}
private void Start()
diff --git a/UnityProject/Assets/GameScripts/HotFix/GameLogic/GameApp_RegisterSystem.cs b/UnityProject/Assets/GameScripts/HotFix/GameLogic/GameApp_RegisterSystem.cs
index 9c973f17..357f72a1 100644
--- a/UnityProject/Assets/GameScripts/HotFix/GameLogic/GameApp_RegisterSystem.cs
+++ b/UnityProject/Assets/GameScripts/HotFix/GameLogic/GameApp_RegisterSystem.cs
@@ -7,7 +7,7 @@ public partial class GameApp
{
private List _listLogicMgr;
- private void Init()
+ public override void Active()
{
CodeTypes.Instance.Init(_hotfixAssembly.ToArray());
EventInterfaceHelper.Init();