using System.Collections.Generic; using UnityEngine; using System; public class GameObjectPoolManager : SingletonMonobehaviour { #if UNITY_EDITOR private Dictionary m_DebugInstIDDict = null; #endif private Dictionary m_PoolDict = null; // 不需要销毁的对象列表 private List dontDestoryGoInstIDList = null; private Transform m_TargetContainer; public void Initialize() { if (m_PoolDict == null) { m_PoolDict = new Dictionary(); } if (!m_TargetContainer) { m_TargetContainer = new GameObject("Container").transform; m_TargetContainer.SetParent(transform); } if (dontDestoryGoInstIDList == null) { dontDestoryGoInstIDList = new List(); } #if UNITY_EDITOR if (m_DebugInstIDDict == null) { m_DebugInstIDDict = new Dictionary(); } #endif } public void AddDontDestroyGoInstID(int id) { if (!dontDestoryGoInstIDList.Contains(id)) { dontDestoryGoInstIDList.Add(id); } } public bool ExistPool(GameObject prefab) { if (prefab == null) { return false; } if (m_PoolDict.ContainsKey(prefab.GetInstanceID())) { return true; } return false; } public GameObjectPool RequestPool(GameObject prefab) { if (prefab == null) { return null; } int _prefabInstanceId = prefab.GetInstanceID(); GameObjectPool _pool = null; if (m_PoolDict.TryGetValue(_prefabInstanceId, out _pool)) { return _pool; } _pool = new GameObjectPool(prefab); m_PoolDict[_prefabInstanceId] = _pool; return _pool; } public void CacheGameObject(GameObject prefab, int count, bool _prefabActive) { if (prefab == null) { return; } RequestPool(prefab).Cache(count, _prefabActive); } public void CacheNpc(int npcID, int count, bool prefabActive) { string _assetName; string _assetBundleName; NPCConfig _m = NPCConfig.Get(npcID); if (_m == null || _m.MODE.Equals("0")) { return; } if (GAMgr.Instance.s_NpcID2Assetname.TryGetValue(npcID, out _assetName)) { _assetBundleName = GAMgr.Instance.s_NpcID2BundleName[npcID]; } else { _assetName = StringUtility.Contact(InstanceResourcesLoader.raceSuffix, _m.MODE); _assetBundleName = StringUtility.Contact(ResourcesPath.MOB_FOLDER_NAME, _assetName); GAMgr.Instance.s_NpcID2Assetname[npcID] = _assetName; GAMgr.Instance.s_NpcID2BundleName[npcID] = _assetBundleName; } GameObject _prefab = InstanceResourcesLoader.LoadMob(_assetBundleName, _assetName); if (!_prefab) { return; } GameObjectPool _pool = RequestPool(_prefab); _pool.assetBundleName = _assetBundleName; _pool.assetName = _assetName; _pool.Cache(count, prefabActive); } public GameObject RequestGameObject(GameObject prefab) { if (prefab == null) { return null; } return RequestPool(prefab).Request(); } public GameObject RequestEmptyJY() { var _prefab = InstanceResourcesLoader.LoadEmptyJY(); if (!_prefab) { return null; } var _pool = RequestPool(_prefab); _pool.assetName = InstanceResourcesLoader.emptyJyName; _pool.assetBundleName = "gmodels/prefab_race_jy"; return _pool.Request(); } public void ReleaseEmptyJY(GameObject go) { var _prefab = InstanceResourcesLoader.LoadEmptyJY(); if (!_prefab) { return; } GameObjectPool _pool = RequestPool(_prefab); if (_pool != null) { _pool.Release(go); } } public GameObject RequestDefaultPet() { GameObject _prefab = InstanceResourcesLoader.LoadMob(GeneralDefine.ModeDefaultConfig[2][0], GeneralDefine.ModeDefaultConfig[2][1]); if (!_prefab) { return null; } GameObjectPool _pool = RequestPool(_prefab); _pool.assetName = GeneralDefine.ModeDefaultConfig[2][1]; _pool.assetBundleName = GeneralDefine.ModeDefaultConfig[2][0]; return _pool.Request(); } public GameObject RequestDefaultFightNpc() { GameObject _prefab = InstanceResourcesLoader.LoadMob(GeneralDefine.ModeDefaultConfig[1][0], GeneralDefine.ModeDefaultConfig[1][1]); if (!_prefab) { return null; } GameObjectPool _pool = RequestPool(_prefab); _pool.assetName = GeneralDefine.ModeDefaultConfig[1][1]; _pool.assetBundleName = GeneralDefine.ModeDefaultConfig[1][0]; return _pool.Request(); } public GameObject RequestDefaultFuncNpc() { GameObject _prefab = InstanceResourcesLoader.LoadMob(GeneralDefine.ModeDefaultConfig[0][0], GeneralDefine.ModeDefaultConfig[0][1]); if (!_prefab) { return null; } GameObjectPool _pool = RequestPool(_prefab); _pool.assetName = GeneralDefine.ModeDefaultConfig[0][1]; _pool.assetBundleName = GeneralDefine.ModeDefaultConfig[0][0]; return _pool.Request(); } public void ReleaseDefaultPet(GameObject go) { GameObject _prefab = InstanceResourcesLoader.LoadMob(GeneralDefine.ModeDefaultConfig[2][0], GeneralDefine.ModeDefaultConfig[2][1]); if (!_prefab) { return; } GameObjectPool _pool = RequestPool(_prefab); if (_pool != null) { _pool.Release(go); } } public void ReleaseDefaultHorse(GameObject go) { GameObject _prefab = InstanceResourcesLoader.LoadMob(GeneralDefine.ModeDefaultConfig[3][0], GeneralDefine.ModeDefaultConfig[3][1]); if (!_prefab) { return; } GameObjectPool _pool = RequestPool(_prefab); if (_pool != null) { _pool.Release(go); } } public void ReleaseDefaultFightNPC(GameObject go) { GameObject _prefab = InstanceResourcesLoader.LoadMob(GeneralDefine.ModeDefaultConfig[1][0], GeneralDefine.ModeDefaultConfig[1][1]); if (!_prefab) { return; } GameObjectPool _pool = RequestPool(_prefab); if (_pool != null) { _pool.Release(go); } } public void ReleaseDefaultFuncNPC(GameObject go) { GameObject _prefab = InstanceResourcesLoader.LoadMob(GeneralDefine.ModeDefaultConfig[0][0], GeneralDefine.ModeDefaultConfig[0][1]); if (!_prefab) { return; } GameObjectPool _pool = RequestPool(_prefab); if (_pool != null) { _pool.Release(go); } } public GameObject RequestNpcGameObject(int npcID) { string _assetName; string _assetBundleName; NPCConfig _m = NPCConfig.Get(npcID); if (_m == null || _m.MODE.Equals("0")) { return null; } if (GAMgr.Instance.s_NpcID2Assetname.TryGetValue(npcID, out _assetName)) { _assetBundleName = GAMgr.Instance.s_NpcID2BundleName[npcID]; } else { _assetName = StringUtility.Contact(InstanceResourcesLoader.raceSuffix, _m.MODE); _assetBundleName = StringUtility.Contact(ResourcesPath.MOB_FOLDER_NAME, _assetName); GAMgr.Instance.s_NpcID2Assetname[npcID] = _assetName; GAMgr.Instance.s_NpcID2BundleName[npcID] = _assetBundleName; } GameObject _prefab = InstanceResourcesLoader.LoadMob(_assetBundleName, _assetName); if (!_prefab) { return null; } GameObjectPool _pool = RequestPool(_prefab); _pool.assetBundleName = _assetBundleName; _pool.assetName = _assetName; return _pool.Request(); } public void ReleaseGameObject(GameObject prefab, GameObject go) { GameObjectPool _pool = RequestPool(prefab); if (_pool == null) { return; } _pool.Release(go); } public void Release(GameObject prefab) { int _prefabInstanceId = prefab.GetInstanceID(); GameObjectPool _pool = null; if (m_PoolDict.TryGetValue(_prefabInstanceId, out _pool)) { _pool.Clear(); if (_pool.IsEmpty()) { m_PoolDict.Remove(_pool.PrefabInstanceId); } } } public void UnLoadNPC(int npcID) { if (!AssetSource.mobFromEditor) { string _assetName; string _assetBundleName; if (!GAMgr.Instance.s_NpcID2Assetname.TryGetValue(npcID, out _assetName)) { return; } _assetBundleName = GAMgr.Instance.s_NpcID2BundleName[npcID]; if (!AssetBundleUtility.Instance.JudgeExistAssetBundle(_assetBundleName)) { return; } GameObject _prefab = InstanceResourcesLoader.LoadMob(_assetBundleName, _assetName); if (!_prefab) { return; } if (!ExistPool(_prefab)) { return; } GameObjectPool _pool = RequestPool(_prefab); _pool.Clear(); m_PoolDict.Remove(_pool.PrefabInstanceId); } } public void UnLoadAll(bool force = false) { List _removeList = new List(); foreach (var _pool in m_PoolDict.Values) { if (GAMgr.Instance.needDestroyPrefabList.Contains(_pool.Prefab)) { _pool.Clear(); _removeList.Add(_pool.PrefabInstanceId); } } for (int i = 0; i < _removeList.Count; ++i) { m_PoolDict.Remove(_removeList[i]); } } public class GameObjectPool { private GameObject m_Prefab = null; public GameObject Prefab { get { return m_Prefab; } } public int PrefabInstanceId { get; private set; } public List m_ActiveList = null; private List m_FreeList = null; Action 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; internal protected GameObjectPool(GameObject prefab) { m_Prefab = prefab; PrefabInstanceId = m_Prefab.GetInstanceID(); m_ActiveList = new List(); m_FreeList = new List(); #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 _callBack) { releaseCallBack = _callBack; } public void RemoveReleaseListener() { releaseCallBack = null; } public void Cache(int count, bool _prefabActive) { GameObject _go; for (int i = 0; i < count; ++i) { _go = Instantiate(m_Prefab, Constants.Special_Hide_Position, Quaternion.identity); m_FreeList.Add(_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.transform.SetParent(m_DebugFree); _debugItem.target = _go; Instance.m_DebugInstIDDict[_go.GetInstanceID()] = _debugItem; #endif var animator = _go.GetComponent(); if (animator != null) { animator.enabled = false; } _go.SetActive(_prefabActive); } } public GameObject Request() { GameObject _go = null; while (m_FreeList.Count > 0) { if (m_FreeList[0] != null) { _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; } else { m_FreeList.RemoveAt(0); } } if (_go == null) { _go = Instantiate(m_Prefab, Constants.Special_Hide_Position, Quaternion.identity); m_ActiveList.Add(_go); #if UNITY_EDITOR && !UNITY_ANDROID && !UNITY_IOS DebugItem _debugItem = new GameObject(_go.GetInstanceID().ToString()).AddMissingComponent(); _debugItem.transform.SetParent(m_DebugActive); _debugItem.target = _go; Instance.m_DebugInstIDDict[_go.GetInstanceID()] = _debugItem; #endif } _go.transform.SetParent(null); _go.transform.localScale = Vector3.one; return _go; } public void Release(GameObject go) { if (go == null) { return; } if (m_ActiveList.Contains(go)) { m_ActiveList.Remove(go); } if (m_FreeList.Contains(go)) { return; } m_FreeList.Add(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())) { DebugItem _debugItem = Instance.m_DebugInstIDDict[go.GetInstanceID()]; _debugItem.transform.SetParent(m_DebugFree); } #endif if (releaseCallBack != null) { releaseCallBack(go); } } public void ReleaseAll() { for (int i = m_ActiveList.Count - 1; i >= 0; i--) { var _go = m_ActiveList[i]; m_ActiveList.Remove(_go); if (!m_FreeList.Contains(_go)) { m_FreeList.Add(_go); } #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); } } } public void Clear() { for (int i = m_ActiveList.Count - 1; i >= 0; --i) { 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) { Debug.LogWarningFormat(" |-- {0}", m_ActiveList[i].name); } } #endif for (int i = m_FreeList.Count - 1; i >= 0; --i) { 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); } #if UNITY_EDITOR && !UNITY_ANDROID && !UNITY_IOS if (m_FreeList.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); } } #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)) { InstanceResourcesLoader.UnloadAsset(assetBundleName, assetName); } } public bool IsEmpty() { return m_ActiveList.Count == 0 && m_FreeList.Count == 0; } } }