|  |  | 
 |  |  | 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>(); | 
 |  |  | 
 |  |  |             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) | 
 |  |  | 
 |  |  |         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(); | 
 |  |  |  | 
 |  |  | 
 |  |  |             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) | 
 |  |  | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         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; | 
 |  |  | 
 |  |  |             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) | 
 |  |  | 
 |  |  |                 _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) | 
 |  |  | 
 |  |  |  | 
 |  |  |                 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; | 
 |  |  |                 } | 
 |  |  |  | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |  | 
 |  |  | 
 |  |  |                 _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) | 
 |  |  |         { | 
 |  |  | 
 |  |  |  | 
 |  |  |             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 | 
 |  |  |  | 
 |  |  | 
 |  |  |             { | 
 |  |  |                 releaseCallBack(go); | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |             // 更新池统计数据 | 
 |  |  |             Instance.UpdatePoolStats(); | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         public void ReleaseAll() | 
 |  |  | 
 |  |  |                     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); | 
 |  |  | 
 |  |  |                  | 
 |  |  |             } | 
 |  |  |             m_ActiveHashSet.Clear(); | 
 |  |  |  | 
 |  |  |             // 更新池统计数据 | 
 |  |  |             Instance.UpdatePoolStats(); | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         public void Clear() | 
 |  |  | 
 |  |  |                  | 
 |  |  |             } | 
 |  |  |  | 
 |  |  | #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); | 
 |  |  | 
 |  |  |             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); | 
 |  |  | 
 |  |  |             if (IsEmpty()) | 
 |  |  |             { | 
 |  |  |                 m_Prefab = null; | 
 |  |  | #if UNITY_EDITOR && !UNITY_ANDROID && !UNITY_IOS | 
 |  |  |                 Destroy(m_DebugContainer.gameObject); | 
 |  |  | #endif | 
 |  |  |  | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |             if (!string.IsNullOrEmpty(assetBundleName) && !string.IsNullOrEmpty(assetName)) |