using System.Collections.Generic;
|
using UnityEngine;
|
using System;
|
|
|
|
public class GameObjectPoolManager : SingletonMonobehaviour<GameObjectPoolManager>
|
{
|
#if UNITY_EDITOR
|
private Dictionary<int, DebugItem> m_DebugInstIDDict = null;
|
#endif
|
private Dictionary<int, GameObjectPool> m_PoolDict = null;
|
|
// 不需要销毁的对象列表
|
private List<int> dontDestoryGoInstIDList = null;
|
|
private Transform m_TargetContainer;
|
|
public void Initialize()
|
{
|
if (m_PoolDict == null)
|
{
|
m_PoolDict = new Dictionary<int, GameObjectPool>();
|
}
|
|
if (!m_TargetContainer)
|
{
|
m_TargetContainer = new GameObject("Container").transform;
|
m_TargetContainer.SetParent(transform);
|
}
|
|
if (dontDestoryGoInstIDList == null)
|
{
|
dontDestoryGoInstIDList = new List<int>();
|
}
|
|
#if UNITY_EDITOR
|
if (m_DebugInstIDDict == null)
|
{
|
m_DebugInstIDDict = new Dictionary<int, DebugItem>();
|
}
|
#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 GameObject RequestGameObject(GameObject prefab)
|
{
|
if (prefab == null)
|
{
|
return null;
|
}
|
|
return RequestPool(prefab).Request();
|
}
|
|
|
public void UnLoadAll(bool force = false)
|
{
|
List<int> _removeList = new List<int>();
|
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<GameObject> m_ActiveList = null;
|
private List<GameObject> m_FreeList = null;
|
|
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;
|
|
internal protected GameObjectPool(GameObject prefab)
|
{
|
m_Prefab = prefab;
|
PrefabInstanceId = m_Prefab.GetInstanceID();
|
m_ActiveList = new List<GameObject>();
|
m_FreeList = new List<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)
|
{
|
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>();
|
_debugItem.transform.SetParent(m_DebugFree);
|
_debugItem.target = _go;
|
Instance.m_DebugInstIDDict[_go.GetInstanceID()] = _debugItem;
|
#endif
|
var animator = _go.GetComponent<Animator>();
|
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>();
|
_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))
|
{
|
ResManager.Instance.UnloadAsset(assetBundleName);
|
}
|
}
|
|
public bool IsEmpty()
|
{
|
return m_ActiveList.Count == 0 && m_FreeList.Count == 0;
|
}
|
}
|
}
|