From cb653cf75b17b9bdca0b5b9e6b88edf1ca72e90c Mon Sep 17 00:00:00 2001
From: hch <305670599@qq.com>
Date: 星期五, 17 十月 2025 09:54:11 +0800
Subject: [PATCH] 0312 删除旧的日常代码3
---
Main/Core/ResModule/GameObjectPoolManager.cs | 424 +++++++++++++++++++++++++++++++++++++---------------
1 files changed, 301 insertions(+), 123 deletions(-)
diff --git a/Main/Core/ResModule/GameObjectPoolManager.cs b/Main/Core/ResModule/GameObjectPoolManager.cs
index dd958a2..942a36e 100644
--- a/Main/Core/ResModule/GameObjectPoolManager.cs
+++ b/Main/Core/ResModule/GameObjectPoolManager.cs
@@ -1,20 +1,170 @@
-锘縰sing System.Collections.Generic;
+using System.Collections.Generic;
using UnityEngine;
using System;
+using Cysharp.Threading.Tasks;
+using System.Linq;
+#if UNITY_EDITOR
+using UnityEngine.Profiling;
+#endif
public class GameObjectPoolManager : SingletonMonobehaviour<GameObjectPoolManager>
{
#if UNITY_EDITOR
- private Dictionary<int, DebugItem> m_DebugInstIDDict = null;
+ private bool m_ShowDebugPanel = false;
+ private Vector2 m_ScrollPosition = Vector2.zero;
+
+
+ private void OnGUI()
+ {
+ if (!m_ShowDebugPanel) return;
+
+ GUILayout.BeginArea(new Rect(10, 10, 400, 600));
+ GUILayout.BeginVertical("Box");
+ m_ScrollPosition = GUILayout.BeginScrollView(m_ScrollPosition, GUILayout.Width(380), GUILayout.Height(580));
+
+ GUILayout.Label("瀵硅薄姹犺皟璇曢潰鏉�", GUILayout.Height(30));
+ LogPoolMemoryUsage();
+ GUILayout.Space(10);
+
+ foreach (var poolEntry in m_PoolDict)
+ {
+ int prefabInstanceId = poolEntry.Key;
+ GameObjectPool pool = poolEntry.Value;
+
+ GUILayout.BeginVertical("Box");
+ GUILayout.Label($"姹犲悕绉�: {pool.Prefab.name}");
+ GUILayout.Label($"娲昏穬瀵硅薄鏁�: {pool.m_ActiveHashSet.Count}");
+ GUILayout.Label($"绌洪棽瀵硅薄鏁�: {pool.m_FreeQueue.Count}");
+ int count = m_PoolUsageFrequency.TryGetValue(prefabInstanceId, out int frequency) ? frequency : 0;
+ GUILayout.Label($"浣跨敤棰戠巼: {count}");
+ GUILayout.EndVertical();
+ GUILayout.Space(5);
+ }
+
+ GUILayout.EndScrollView();
+ GUILayout.EndVertical();
+ GUILayout.EndArea();
+ }
+
+ [UnityEditor.MenuItem("Tools/瀵硅薄姹�/鏄剧ず璋冭瘯闈㈡澘")]
+ private static void ToggleDebugPanel()
+ {
+ if (Instance != null)
+ {
+ Instance.m_ShowDebugPanel = !Instance.m_ShowDebugPanel;
+ }
+ }
+
+ public void LogPoolMemoryUsage()
+ {
+ long totalMemory = 0;
+ long totalFreeMemory = 0;
+ var prefabMemoryDict = new Dictionary<string, long>();
+
+ foreach (var poolEntry in m_PoolDict)
+ {
+ int prefabInstanceId = poolEntry.Key;
+ GameObjectPool pool = poolEntry.Value;
+ string prefabName = pool.Prefab.name;
+ long prefabMemory = 0;
+ long freeMemory = 0;
+
+ // 璁$畻娲昏穬瀵硅薄鐨勫唴瀛樺崰鐢�
+ foreach (var gameObject in pool.m_ActiveHashSet)
+ {
+ if (gameObject != null)
+ {
+ long memory = Profiler.GetRuntimeMemorySizeLong(gameObject);
+ prefabMemory += memory;
+ }
+ }
+
+ // 璁$畻绌洪棽瀵硅薄鐨勫唴瀛樺崰鐢�
+ foreach (var gameObject in pool.m_FreeQueue)
+ {
+ if (gameObject != null)
+ {
+ long memory = Profiler.GetRuntimeMemorySizeLong(gameObject);
+ prefabMemory += memory;
+ freeMemory += memory;
+ }
+ }
+
+ totalMemory += prefabMemory;
+ totalFreeMemory += freeMemory;
+ prefabMemoryDict[prefabName] = prefabMemory;
+ }
+
+ // 鎸夊唴瀛樺崰鐢ㄦ帓搴�
+ var sortedPrefabs = prefabMemoryDict.OrderByDescending(kv => kv.Value).Take(3).ToList();
+
+ GUILayout.Label($"鎬诲唴瀛樺崰鐢�: {totalMemory / 1024} KB", GUILayout.Height(30));
+ GUILayout.Label($"绌洪棽鍐呭瓨鍗犵敤: {totalFreeMemory / 1024} KB", GUILayout.Height(30));
+ GUILayout.Label("鍗犵敤鏈�楂樼殑鍓�3棰勫埗浣撳悕:", GUILayout.Height(30));
+ foreach (var prefabInstance in sortedPrefabs)
+ {
+ GUILayout.BeginHorizontal("Box");
+ GUILayout.Label($"{prefabInstance.Key}({prefabInstance.Value / 1024} KB)", GUILayout.Height(25));
+ GUILayout.EndHorizontal();
+ }
+
+ }
+
+
#endif
+ // 姹犵粺璁℃暟鎹�
+ public Dictionary<int, PoolStats> PoolStatistics { get; private set; } = new Dictionary<int, PoolStats>();
+
+ public class PoolStats
+ {
+ public int TotalObjects { get; set; }
+ public int ActiveObjects { get; set; }
+ public int FreeObjects { get; set; }
+ public int UsageFrequency { get; set; }
+ }
+
+ // 鏇存柊姹犵粺璁℃暟鎹�
+ private void UpdatePoolStats()
+ {
+ if (m_PoolDict == null)
+ return;
+
+ foreach (var poolEntry in m_PoolDict)
+ {
+ int prefabInstanceId = poolEntry.Key;
+ GameObjectPool pool = poolEntry.Value;
+
+ if (!PoolStatistics.ContainsKey(prefabInstanceId))
+ {
+ PoolStatistics[prefabInstanceId] = new PoolStats();
+ }
+
+ PoolStats stats = PoolStatistics[prefabInstanceId];
+ stats.TotalObjects = pool.m_ActiveHashSet.Count + pool.m_FreeQueue.Count;
+ stats.ActiveObjects = pool.m_ActiveHashSet.Count;
+ stats.FreeObjects = pool.m_FreeQueue.Count;
+ stats.UsageFrequency = m_PoolUsageFrequency.TryGetValue(prefabInstanceId, out int frequency) ? frequency : 0;
+ }
+ }
+
+
private Dictionary<int, GameObjectPool> m_PoolDict = null;
// 涓嶉渶瑕侀攢姣佺殑瀵硅薄鍒楄〃
private List<int> dontDestoryGoInstIDList = null;
private Transform m_TargetContainer;
+
+ // 瀹氭湡妫�鏌ユ睜鐨勬椂闂撮棿闅旓紙绉掞級
+ private float m_PoolCheckInterval = 600f;
+
+ // 璁板綍姣忎釜姹犵殑浣跨敤棰戠巼
+ private Dictionary<int, int> m_PoolUsageFrequency = new Dictionary<int, int>();
+
+ //闇�瑕佸姩鎬佸嵏杞界殑棰勫埗浣擄紝渚嬪鍒囨崲鍦烘櫙鏃�
+ public List<GameObject> needDestroyPrefabList = new List<GameObject>();
public void Initialize()
{
@@ -34,12 +184,40 @@
dontDestoryGoInstIDList = new List<int>();
}
-#if UNITY_EDITOR
- if (m_DebugInstIDDict == null)
+ // 鍚姩瀹氭湡妫�鏌ユ睜鐨勫崗绋�
+ CheckPoolUsage();
+ }
+
+ private async UniTask CheckPoolUsage()
+ {
+ while (true)
{
- m_DebugInstIDDict = new Dictionary<int, DebugItem>();
+ await UniTask.Delay(TimeSpan.FromSeconds(m_PoolCheckInterval));
+
+ foreach (var poolEntry in m_PoolDict)
+ {
+ int prefabInstanceId = poolEntry.Key;
+ GameObjectPool pool = poolEntry.Value;
+
+ // 濡傛灉姹犵殑浣跨敤棰戠巼浣庝簬闃堝�硷紝鍑忓皯姹犵殑澶у皬
+ if (m_PoolUsageFrequency.TryGetValue(prefabInstanceId, out int usageCount) && usageCount < 5)
+ {
+ // 淇濈暀鑷冲皯涓�涓璞★紝閬垮厤棰戠箒鍒涘缓鍜岄攢姣�
+ int targetSize = Mathf.Max(1, pool.m_FreeQueue.Count / 2);
+ while (pool.m_FreeQueue.Count > targetSize)
+ {
+ GameObject obj = pool.m_FreeQueue.Dequeue();
+ if (!dontDestoryGoInstIDList.Contains(obj.GetInstanceID()))
+ {
+ Destroy(obj);
+ }
+ }
+ }
+
+ // 閲嶇疆浣跨敤棰戠巼
+ m_PoolUsageFrequency[prefabInstanceId] = 0;
+ }
}
-#endif
}
public void AddDontDestroyGoInstID(int id)
@@ -65,12 +243,26 @@
return false;
}
+ /// <summary>
+ /// 浼犲叆鐨勪负棰勫埗浣擄紝鑰岄潪缁勪欢锛屽惁鍒欎細瀵艰嚧GetInstanceID绠$悊娣蜂贡锛屾瘡娆″疄渚嬪寲閮戒細鏀瑰彉
+ /// </summary>
+ /// <param name="prefab"></param>
+ /// <returns></returns>
public GameObjectPool RequestPool(GameObject prefab)
{
if (prefab == null)
{
return null;
}
+
+#if UNITY_EDITOR
+ if (UnityEditor.PrefabUtility.GetPrefabAssetType(prefab) == UnityEditor.PrefabAssetType.NotAPrefab)
+ {
+ Debug.LogError($"{prefab.name}涓嶆槸涓�涓鍒朵綋锛�");
+ return null;
+ }
+#endif
+
int _prefabInstanceId = prefab.GetInstanceID();
@@ -105,20 +297,28 @@
return null;
}
+#if UNITY_EDITOR
+ if (UnityEditor.PrefabUtility.GetPrefabAssetType(prefab) == UnityEditor.PrefabAssetType.NotAPrefab)
+ {
+ Debug.LogError($"{prefab.name}涓嶆槸涓�涓鍒朵綋锛�");
+ return null;
+ }
+#endif
return RequestPool(prefab).Request();
}
+ //鐗瑰畾鎯呭喌涓嬮渶瑕佸姩鎬佸嵏杞界殑锛屽鍒囨崲鍦烘櫙鏃�
public void UnLoadAll(bool force = false)
{
List<int> _removeList = new List<int>();
foreach (var _pool in m_PoolDict.Values)
{
- // if (GAMgr.Instance.needDestroyPrefabList.Contains(_pool.Prefab))
- // {
+ if (needDestroyPrefabList.Contains(_pool.Prefab))
+ {
_pool.Clear();
_removeList.Add(_pool.PrefabInstanceId);
- // }
+ }
}
for (int i = 0; i < _removeList.Count; ++i)
@@ -137,20 +337,19 @@
return m_Prefab;
}
}
+
+ //棰勫埗浣撳疄渚媔d锛岀敤浜庢绱㈡睜
public int PrefabInstanceId
{
get; private set;
}
- public List<GameObject> m_ActiveList = null;
- private List<GameObject> m_FreeList = null;
+ public HashSet<GameObject> m_ActiveHashSet = new HashSet<GameObject>();
+ public Queue<GameObject> m_FreeQueue = null;
+ private int Pool_FreeList_Warning_Threshold = 10; //褰撶┖闂插璞¢珮浜庢鍊兼椂锛屼細杩涜鏃ュ織杈撳嚭鎻愰啋
Action<GameObject> releaseCallBack;
-#if UNITY_EDITOR && !UNITY_ANDROID && !UNITY_IOS
- private Transform m_DebugContainer;
- private Transform m_DebugActive;
- private Transform m_DebugFree;
-#endif
+
public string assetBundleName;
public string assetName;
@@ -159,17 +358,9 @@
{
m_Prefab = prefab;
PrefabInstanceId = m_Prefab.GetInstanceID();
- m_ActiveList = new List<GameObject>();
- m_FreeList = new List<GameObject>();
+ m_ActiveHashSet = new HashSet<GameObject>();
+ m_FreeQueue = new Queue<GameObject>();
-#if UNITY_EDITOR && !UNITY_ANDROID && !UNITY_IOS
- m_DebugContainer = new GameObject(prefab.name).transform;
- m_DebugActive = new GameObject("Active").transform;
- m_DebugFree = new GameObject("Free").transform;
- m_DebugActive.SetParent(m_DebugContainer);
- m_DebugFree.SetParent(m_DebugContainer);
- m_DebugContainer.SetParent(Instance.transform);
-#endif
}
public void AddReleaseListener(Action<GameObject> _callBack)
@@ -188,16 +379,17 @@
for (int i = 0; i < count; ++i)
{
_go = Instantiate(m_Prefab, Constants.Special_Hide_Position, Quaternion.identity);
- m_FreeList.Add(_go);
+ m_FreeQueue.Enqueue(_go);
_go.transform.SetParent(Instance.m_TargetContainer);
_go.transform.position = Constants.Special_Hide_Position;
-#if UNITY_EDITOR && !UNITY_ANDROID && !UNITY_IOS
- DebugItem _debugItem = new GameObject(_go.GetInstanceID().ToString()).AddMissingComponent<DebugItem>();
- _debugItem.transform.SetParent(m_DebugFree);
- _debugItem.target = _go;
- Instance.m_DebugInstIDDict[_go.GetInstanceID()] = _debugItem;
+#if UNITY_EDITOR
+ // 妫�鏌ョ┖闂插垪琛ㄦ暟閲忔槸鍚﹁秴杩囬槇鍊�
+ if (m_FreeQueue.Count > Pool_FreeList_Warning_Threshold)
+ {
+ Debug.LogWarning($"GameObjectPool {m_Prefab.name} 鐨勭┖闂插璞℃暟閲� ({m_FreeQueue.Count}) 瓒呰繃闃堝�� ({Pool_FreeList_Warning_Threshold})锛岃妫�鏌ユ槸鍚﹂渶瑕佹竻鐞嗐��");
+ }
#endif
var animator = _go.GetComponent<Animator>();
if (animator != null)
@@ -212,48 +404,41 @@
{
GameObject _go = null;
- while (m_FreeList.Count > 0)
+ if (m_FreeQueue.Count > 0)
{
- if (m_FreeList[0] != null)
+ _go = m_FreeQueue.Dequeue();
+
+ m_ActiveHashSet.Add(_go);
+
+ // 缁熻姹犵殑浣跨敤棰戠巼
+ if (Instance.m_PoolUsageFrequency.ContainsKey(m_Prefab.GetInstanceID()))
{
- _go = m_FreeList[0];
-
- m_ActiveList.Add(_go);
- m_FreeList.RemoveAt(0);
-
-#if UNITY_EDITOR && !UNITY_ANDROID && !UNITY_IOS
- if (Instance.m_DebugInstIDDict.ContainsKey(_go.GetInstanceID()))
- {
- DebugItem _debugItem = Instance.m_DebugInstIDDict[_go.GetInstanceID()];
- _debugItem.transform.SetParent(m_DebugActive);
- }
-#endif
- break;
+ Instance.m_PoolUsageFrequency[m_Prefab.GetInstanceID()]++;
}
else
{
- m_FreeList.RemoveAt(0);
+ Instance.m_PoolUsageFrequency[m_Prefab.GetInstanceID()] = 1;
}
+
}
+
if (_go == null)
{
_go = Instantiate(m_Prefab, Constants.Special_Hide_Position, Quaternion.identity);
- m_ActiveList.Add(_go);
+ m_ActiveHashSet.Add(_go);
-#if UNITY_EDITOR && !UNITY_ANDROID && !UNITY_IOS
- DebugItem _debugItem = new GameObject(_go.GetInstanceID().ToString()).AddMissingComponent<DebugItem>();
- _debugItem.transform.SetParent(m_DebugActive);
- _debugItem.target = _go;
- Instance.m_DebugInstIDDict[_go.GetInstanceID()] = _debugItem;
-#endif
}
_go.transform.SetParent(null);
_go.transform.localScale = Vector3.one;
+ // 鏇存柊姹犵粺璁℃暟鎹�
+ Instance.UpdatePoolStats();
+
return _go;
}
+
public void Release(GameObject go)
{
@@ -261,24 +446,19 @@
{
return;
}
- if (m_ActiveList.Contains(go))
- {
- m_ActiveList.Remove(go);
- }
- if (m_FreeList.Contains(go))
- {
- return;
- }
+ m_ActiveHashSet.Remove(go);
- m_FreeList.Add(go);
+ m_FreeQueue.Enqueue(go);
go.transform.SetParent(Instance.m_TargetContainer);
+
go.transform.position = Constants.Special_Hide_Position;
-#if UNITY_EDITOR && !UNITY_ANDROID && !UNITY_IOS
- if (Instance.m_DebugInstIDDict.ContainsKey(go.GetInstanceID()))
+
+#if UNITY_EDITOR
+ // 妫�鏌ョ┖闂插垪琛ㄦ暟閲忔槸鍚﹁秴杩囬槇鍊�
+ if (m_FreeQueue.Count > Pool_FreeList_Warning_Threshold)
{
- DebugItem _debugItem = Instance.m_DebugInstIDDict[go.GetInstanceID()];
- _debugItem.transform.SetParent(m_DebugFree);
+ Debug.LogWarning($"GameObjectPool {m_Prefab.name} 鐨勭┖闂插璞℃暟閲� ({m_FreeQueue.Count}) 瓒呰繃闃堝�� ({Pool_FreeList_Warning_Threshold})锛岃妫�鏌ユ槸鍚﹂渶瑕佹竻鐞嗐��");
}
#endif
@@ -286,98 +466,96 @@
{
releaseCallBack(go);
}
+
+ // 鏇存柊姹犵粺璁℃暟鎹�
+ Instance.UpdatePoolStats();
}
public void ReleaseAll()
{
- for (int i = m_ActiveList.Count - 1; i >= 0; i--)
+ //閲婃斁 m_ActiveHashSet涓� 鐨凣ameObject锛屾帓闄�
+ foreach (GameObject go in m_ActiveHashSet)
{
- var _go = m_ActiveList[i];
- m_ActiveList.Remove(_go);
-
- if (!m_FreeList.Contains(_go))
+ if (go != null)
{
- m_FreeList.Add(_go);
- }
+ m_FreeQueue.Enqueue(go);
+ go.transform.SetParent(Instance.m_TargetContainer);
+ go.transform.position = Constants.Special_Hide_Position;
-#if UNITY_EDITOR && !UNITY_ANDROID && !UNITY_IOS
- DebugItem _debugItem = Instance.m_DebugInstIDDict[_go.GetInstanceID()];
- _debugItem.transform.SetParent(m_DebugFree);
-#endif
- _go.transform.SetParent(Instance.m_TargetContainer);
- _go.transform.position = Constants.Special_Hide_Position;
-
- if (releaseCallBack != null)
- {
- releaseCallBack(_go);
+ if (releaseCallBack != null)
+ {
+ releaseCallBack(go);
+ }
}
+
}
+ m_ActiveHashSet.Clear();
+
+ // 鏇存柊姹犵粺璁℃暟鎹�
+ Instance.UpdatePoolStats();
}
public void Clear()
{
- for (int i = m_ActiveList.Count - 1; i >= 0; --i)
+ foreach (GameObject go in m_ActiveHashSet)
{
- if (m_ActiveList[i] == null
- || Instance.dontDestoryGoInstIDList.Contains(m_ActiveList[i].GetInstanceID()))
- continue;
-#if UNITY_EDITOR && !UNITY_ANDROID && !UNITY_IOS
- Destroy(Instance.m_DebugInstIDDict[m_ActiveList[i].GetInstanceID()].gameObject);
-#endif
- Destroy(m_ActiveList[i]);
- m_ActiveList.RemoveAt(i);
- }
-
-#if UNITY_EDITOR && !UNITY_ANDROID && !UNITY_IOS
- if (m_ActiveList.Count != 0)
- {
- Debug.LogWarningFormat("{0} 姹犳竻鐞嗗悗, 杩樻湁 {1} 涓椿璺冨璞�. ", m_Prefab.name, m_ActiveList.Count);
- for (int i = 0; i < m_ActiveList.Count; ++i)
+ if (go != null)
{
- Debug.LogWarningFormat(" |-- {0}", m_ActiveList[i].name);
+ if (!Instance.dontDestoryGoInstIDList.Contains(go.GetInstanceID()))
+ {
+ m_ActiveHashSet.Remove(go);
+ Destroy(go);
+ }
+
}
+
+ }
+
+#if UNITY_EDITOR
+ if (m_ActiveHashSet.Count != 0)
+ {
+ Debug.LogWarningFormat("{0} 姹犳竻鐞嗗悗, 杩樻湁 {1} 涓椿璺冨璞�. ", m_Prefab.name, m_ActiveHashSet.Count);
}
#endif
- for (int i = m_FreeList.Count - 1; i >= 0; --i)
+ Queue<GameObject> tempQueue = new Queue<GameObject>();
+ while (m_FreeQueue.Count > 0)
{
- if (m_FreeList[i] == null
- || Instance.dontDestoryGoInstIDList.Contains(m_FreeList[i].GetInstanceID()))
- continue;
-#if UNITY_EDITOR && !UNITY_ANDROID && !UNITY_IOS
- Destroy(Instance.m_DebugInstIDDict[m_FreeList[i].GetInstanceID()].gameObject);
-#endif
- Destroy(m_FreeList[i]);
- m_FreeList.RemoveAt(i);
+ GameObject obj = m_FreeQueue.Dequeue();
+ if (Instance.dontDestoryGoInstIDList.Contains(obj.GetInstanceID()))
+ tempQueue.Enqueue(obj);
+ else
+ Destroy(obj);
}
+ m_FreeQueue = tempQueue;
-#if UNITY_EDITOR && !UNITY_ANDROID && !UNITY_IOS
- if (m_FreeList.Count != 0)
+
+#if UNITY_EDITOR
+ if (m_FreeQueue.Count != 0)
{
- Debug.LogWarningFormat("{0} 姹犳竻鐞嗗悗, 杩樻湁 {1} 涓┖闂插璞�. ", m_Prefab.name, m_FreeList.Count);
- for (int i = 0; i < m_FreeList.Count; ++i)
- {
- Debug.LogWarningFormat(" |-- {0}", m_FreeList[i].name);
- }
+ Debug.LogWarningFormat("{0} 姹犳竻鐞嗗悗, 杩樻湁 {1} 涓┖闂插璞�. ", m_Prefab.name, m_FreeQueue.Count);
+ // for (int i = 0; i < m_FreeList.Count; ++i)
+ // {
+ // Debug.LogWarningFormat(" |-- {0}", m_FreeList[i].name);
+ // }
}
#endif
if (IsEmpty())
{
m_Prefab = null;
-#if UNITY_EDITOR && !UNITY_ANDROID && !UNITY_IOS
- Destroy(m_DebugContainer.gameObject);
-#endif
+
}
if (!string.IsNullOrEmpty(assetBundleName) && !string.IsNullOrEmpty(assetName))
{
- ResManager.Instance.UnloadAsset(assetBundleName);
+ ResManager.Instance.UnloadAsset(assetBundleName, assetName);
+ // ResManager.Instance.UnloadAssetBundle(assetBundleName, true, false);
}
}
public bool IsEmpty()
{
- return m_ActiveList.Count == 0 && m_FreeList.Count == 0;
+ return m_ActiveHashSet.Count == 0 && m_FreeQueue.Count == 0;
}
}
}
--
Gitblit v1.8.0