|  |  |  | 
|---|
|  |  |  | 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>(); | 
|---|