|  |  | 
 |  |  | using UnityEngine; | 
 |  |  | using System; | 
 |  |  | using Cysharp.Threading.Tasks; | 
 |  |  | using System.Linq; | 
 |  |  |  | 
 |  |  | #if UNITY_EDITOR | 
 |  |  | using UnityEngine.Profiling; | 
 |  |  | #endif | 
 |  |  |  | 
 |  |  |  | 
 |  |  | public class GameObjectPoolManager : SingletonMonobehaviour<GameObjectPoolManager> | 
 |  |  | 
 |  |  |     private bool m_ShowDebugPanel = false; | 
 |  |  |     private Vector2 m_ScrollPosition = Vector2.zero; | 
 |  |  |  | 
 |  |  |      | 
 |  |  |     private void OnGUI() | 
 |  |  |     { | 
 |  |  |         if (!m_ShowDebugPanel) return; | 
 |  |  | 
 |  |  |         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) | 
 |  |  | 
 |  |  |             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>(); |