From aa72688fbfcba5cf8d90a7b34700bbe1f9ebee12 Mon Sep 17 00:00:00 2001 From: hch <305670599@qq.com> Date: 星期四, 11 九月 2025 22:26:52 +0800 Subject: [PATCH] 0312 自动战斗打BOSS暂停 --- Main/Core/ResModule/GameObjectPoolManager.cs | 296 +++++++++++++++++++++++++++++++++++++++++++++++------------ 1 files changed, 235 insertions(+), 61 deletions(-) diff --git a/Main/Core/ResModule/GameObjectPoolManager.cs b/Main/Core/ResModule/GameObjectPoolManager.cs index eac955c..942a36e 100644 --- a/Main/Core/ResModule/GameObjectPoolManager.cs +++ b/Main/Core/ResModule/GameObjectPoolManager.cs @@ -1,20 +1,167 @@ 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>(); @@ -37,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) @@ -68,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(); @@ -108,8 +297,16 @@ 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) @@ -148,15 +345,11 @@ } public HashSet<GameObject> m_ActiveHashSet = new HashSet<GameObject>(); - private Queue<GameObject> m_FreeQueue = null; - private int Pool_FreeList_Warning_Threshold = 8; + 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; @@ -168,14 +361,6 @@ 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) @@ -199,17 +384,12 @@ _go.transform.position = Constants.Special_Hide_Position; -#if UNITY_EDITOR && !UNITY_ANDROID && !UNITY_IOS +#if UNITY_EDITOR // 妫�鏌ョ┖闂插垪琛ㄦ暟閲忔槸鍚﹁秴杩囬槇鍊� - if (m_FreeList.Count > Pool_FreeList_Warning_Threshold) + if (m_FreeQueue.Count > Pool_FreeList_Warning_Threshold) { - Debug.LogWarning($"GameObjectPool {m_Prefab.name} 鐨勭┖闂插璞℃暟閲� ({m_FreeList.Count}) 瓒呰繃闃堝�� ({Pool_FreeList_Warning_Threshold})锛岃妫�鏌ユ槸鍚﹂渶瑕佹竻鐞嗐��"); + Debug.LogWarning($"GameObjectPool {m_Prefab.name} 鐨勭┖闂插璞℃暟閲� ({m_FreeQueue.Count}) 瓒呰繃闃堝�� ({Pool_FreeList_Warning_Threshold})锛岃妫�鏌ユ槸鍚﹂渶瑕佹竻鐞嗐��"); } - - DebugItem _debugItem = new GameObject(_go.GetInstanceID().ToString()).AddMissingComponent<DebugItem>(); - _debugItem.transform.SetParent(m_DebugFree); - _debugItem.target = _go; - Instance.m_DebugInstIDDict[_go.GetInstanceID()] = _debugItem; #endif var animator = _go.GetComponent<Animator>(); if (animator != null) @@ -230,13 +410,16 @@ m_ActiveHashSet.Add(_go); -#if UNITY_EDITOR && !UNITY_ANDROID && !UNITY_IOS - if (Instance.m_DebugInstIDDict.ContainsKey(_go.GetInstanceID())) + // 缁熻姹犵殑浣跨敤棰戠巼 + if (Instance.m_PoolUsageFrequency.ContainsKey(m_Prefab.GetInstanceID())) { - DebugItem _debugItem = Instance.m_DebugInstIDDict[_go.GetInstanceID()]; - _debugItem.transform.SetParent(m_DebugActive); + Instance.m_PoolUsageFrequency[m_Prefab.GetInstanceID()]++; } -#endif + else + { + Instance.m_PoolUsageFrequency[m_Prefab.GetInstanceID()] = 1; + } + } @@ -245,19 +428,17 @@ _go = Instantiate(m_Prefab, Constants.Special_Hide_Position, Quaternion.identity); 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) { @@ -269,19 +450,15 @@ 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 UNITY_EDITOR // 妫�鏌ョ┖闂插垪琛ㄦ暟閲忔槸鍚﹁秴杩囬槇鍊� - if (m_FreeList.Count > Pool_FreeList_Warning_Threshold) + if (m_FreeQueue.Count > Pool_FreeList_Warning_Threshold) { - Debug.LogWarning($"GameObjectPool {m_Prefab.name} 鐨勭┖闂插璞℃暟閲� ({m_FreeList.Count}) 瓒呰繃闃堝�� ({Pool_FreeList_Warning_Threshold})锛岃妫�鏌ユ槸鍚﹂渶瑕佹竻鐞嗐��"); - } - if (Instance.m_DebugInstIDDict.ContainsKey(go.GetInstanceID())) - { - 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 @@ -289,6 +466,9 @@ { releaseCallBack(go); } + + // 鏇存柊姹犵粺璁℃暟鎹� + Instance.UpdatePoolStats(); } public void ReleaseAll() @@ -302,13 +482,6 @@ 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())) - { - DebugItem _debugItem = Instance.m_DebugInstIDDict[go.GetInstanceID()]; - _debugItem.transform.SetParent(m_DebugFree); - } -#endif if (releaseCallBack != null) { releaseCallBack(go); @@ -317,6 +490,9 @@ } m_ActiveHashSet.Clear(); + + // 鏇存柊姹犵粺璁℃暟鎹� + Instance.UpdatePoolStats(); } public void Clear() @@ -335,7 +511,7 @@ } -#if UNITY_EDITOR && !UNITY_ANDROID && !UNITY_IOS +#if UNITY_EDITOR if (m_ActiveHashSet.Count != 0) { Debug.LogWarningFormat("{0} 姹犳竻鐞嗗悗, 杩樻湁 {1} 涓椿璺冨璞�. ", m_Prefab.name, m_ActiveHashSet.Count); @@ -354,10 +530,10 @@ 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); + 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); @@ -367,9 +543,7 @@ if (IsEmpty()) { m_Prefab = null; -#if UNITY_EDITOR && !UNITY_ANDROID && !UNITY_IOS - Destroy(m_DebugContainer.gameObject); -#endif + } if (!string.IsNullOrEmpty(assetBundleName) && !string.IsNullOrEmpty(assetName)) -- Gitblit v1.8.0