版权声明:欢迎大家留言讨论共同进步,转载请注明出处 https://blog.csdn.net/qq_39108767/article/details/83448195
最近做一款音乐游戏,需要显示较多的音符,需频繁回收利用GameObject,简易的对象池满足不了需求,以前写过几个对象池, 使用起来有比较有局限性,不是很方便,就考虑写一个通用的对象池,可以适用于各种项目类型,而且调用要简便。参考了一些资料,并利用This添加了静态方法,方便调用,就此有了万能对象池~(大佬们看见不要打我 ···)
使用前只需要创建一个池,加载对象到场景时调用创建方法,销毁时调用回收方法即可~~
调用,对~ 就是这么简单,prefab可以是GameObject,也可以是任意组件、自定义的类,适用于各种情况。
void Test()
{
//创建对象池
prefab.CreatePool();
//生成池对象
prefab.Create();
//回收池对象
prefab.Reset();
}
对象池部分,代码比较简单,不多说
public sealed class GenericPool : Singleton<GenericPool>
{
//预加载对象池启动方式
public enum StartupPoolMode { Awake, Start, Manual };
[System.Serializable]
public class StartupPool
{
public GameObject prefab;
public int size;
}
// ----------
static List<GameObject> tempList = new List<GameObject>();
//池内对象<prefab, list<obj>> 经过实测, List效率比Queue高
Dictionary<GameObject, List<GameObject>> idlePoolDic = new Dictionary<GameObject, List<GameObject>>();
//池外对象<obj, prefab>
Dictionary<GameObject, GameObject> workItemDic = new Dictionary<GameObject, GameObject>();
//池对象父物体<prefab, parentTrans>
Dictionary<GameObject, Transform> poolParentDic = new Dictionary<GameObject, Transform>();
//开启方式
[SerializeField, Header("对象池启动方式")] StartupPoolMode startupPoolMode;
[SerializeField, Header("预加载对象池")] StartupPool[] startupPools;
void Awake()
{
if (startupPoolMode == StartupPoolMode.Awake)
StartupPools();
}
void Start()
{
if (startupPoolMode == StartupPoolMode.Start)
StartupPools();
}
//是否已开启pools, 保证只执行一次
bool isStartup;
public void StartupPools()
{
if (isStartup)
{
isStartup = true;
if (startupPools != null && startupPools.Length > 0)
for (int i = 0; i < startupPools.Length; i++)
CreatePool(startupPools[i].prefab, startupPools[i].size);
}
}
// ----- 创建对象池 -----
public static bool CreatePool<T>(T prefab, int initialPoolSize) where T : Component
{
return CreatePool(prefab.gameObject, initialPoolSize);
}
public static bool CreatePool(GameObject prefab, int initialPoolSize)
{
if (prefab != null && !Instance.idlePoolDic.ContainsKey(prefab))
{
List<GameObject> list = new List<GameObject>();
//创建父节点
Transform poolParent = new GameObject("Pool_" + prefab.name).transform;
poolParent.gameObject.SetActive(false);
poolParent.SetParent(Instance.transform);
Instance.poolParentDic.Add(prefab, poolParent);
if (initialPoolSize > 0)
{
for (int i = 0; i < initialPoolSize; i++)
{
GameObject obj = Instantiate(prefab);
obj.transform.SetParent(poolParent);
list.Add(obj);
}
}
Instance.idlePoolDic.Add(prefab, list);
return true;
}
return false;
}
// ----- 获取池对象 -----
public static T Create<T>(T prefab) where T : Component
{
return Create(prefab.gameObject, null, Vector3.zero, Quaternion.identity).GetComponent<T>();
}
public static T Create<T>(T prefab, Transform parent) where T : Component
{
return Create(prefab.gameObject, parent, Vector3.zero, Quaternion.identity).GetComponent<T>();
}
public static T Create<T>(T prefab, Vector3 position) where T : Component
{
return Create(prefab.gameObject, null, position, Quaternion.identity).GetComponent<T>();
}
public static T Create<T>(T prefab, Transform parent, Vector3 position) where T : Component
{
return Create(prefab.gameObject, parent, position, Quaternion.identity).GetComponent<T>();
}
public static T Create<T>(T prefab, Vector3 position, Quaternion rotation) where T : Component
{
return Create(prefab.gameObject, null, position, rotation).GetComponent<T>();
}
public static T Create<T>(T prefab, Transform parent, Vector3 position, Quaternion rotation) where T : Component
{
return Create(prefab.gameObject, parent, position, rotation).GetComponent<T>();
}
public static GameObject Create(GameObject prefab)
{
return Create(prefab, null, Vector3.zero, Quaternion.identity);
}
public static GameObject Create(GameObject prefab, Transform parent)
{
return Create(prefab, parent, Vector3.zero, Quaternion.identity);
}
public static GameObject Create(GameObject prefab, Vector3 position)
{
return Create(prefab, null, position, Quaternion.identity);
}
public static GameObject Create(GameObject prefab, Transform parent, Vector3 position)
{
return Create(prefab, parent, position, Quaternion.identity);
}
public static GameObject Create(GameObject prefab, Vector3 position, Quaternion rotation)
{
return Create(prefab, null, position, rotation);
}
public static GameObject Create(GameObject prefab, Transform parent, Vector3 position, Quaternion rotation)
{
List<GameObject> list;
GameObject obj;
if (Instance.idlePoolDic.TryGetValue(prefab, out list))
{
obj = null;
if (list.Count > 0)
{
while (obj == null && list.Count > 0)
{
obj = list[0];
list.RemoveAt(0);
}
if (obj != null)
{
SetObjParame(obj, parent, position, rotation);
Instance.workItemDic.Add(obj, prefab);
return obj;
}
}
obj = Instantiate(prefab);
SetObjParame(obj, parent, position, rotation);
Instance.workItemDic.Add(obj, prefab);
return obj;
}
//不在对象池内
obj = Instantiate(prefab);
SetObjParame(obj, parent, position, rotation);
return obj;
}
static void SetObjParame(GameObject obj, Transform parent, Vector3 position, Quaternion rotation)
{
obj.transform.SetParent(parent);
obj.transform.localPosition = position;
obj.transform.localRotation = rotation;
}
// ----- 回收池对象 -----
public static void Reset<T>(T obj) where T : Component
{
Reset(obj.gameObject);
}
public static void Reset(GameObject obj)
{
GameObject prefab;
//在池内, 回收, 不在则销毁
if (Instance.workItemDic.TryGetValue(obj, out prefab))
Reset(obj, prefab);
else
Destroy(obj);
}
static void Reset(GameObject obj, GameObject prefab)
{
Instance.idlePoolDic[prefab].Add(obj);
Instance.workItemDic.Remove(obj);
obj.transform.SetParent(Instance.poolParentDic[prefab]);
}
public static void ResetAll<T>(T prefab) where T : Component
{
ResetAll(prefab.gameObject);
}
public static void ResetAll(GameObject prefab)
{
foreach (var item in Instance.workItemDic)
{
if (item.Value == prefab)
tempList.Add(item.Key);
}
for (int i = 0; i < tempList.Count; ++i)
{
Reset(tempList[i], prefab);
}
tempList.Clear();
}
public static void ResetAll()
{
tempList.AddRange(Instance.workItemDic.Keys);
for (int i = 0; i < tempList.Count; ++i)
{
Reset(tempList[i]);
}
tempList.Clear();
}
// ----- 销毁对象池 -----
public static void DestroyPoolIdle<T>(T prefab) where T : Component
{
DestroyPoolIdle(prefab.gameObject);
}
public static void DestroyPoolIdle(GameObject prefab)
{
List<GameObject> pool;
if (Instance.idlePoolDic.TryGetValue(prefab, out pool))
{
for (int i = 0; i < pool.Count; ++i)
{
Destroy(pool[i]);
}
pool.Clear();
}
}
public static void DestroyPoolAll<T>(T prefab) where T : Component
{
DestroyPoolAll(prefab.gameObject);
}
public static void DestroyPoolAll(GameObject prefab)
{
ResetAll(prefab);
DestroyPoolIdle(prefab);
Destroy(Instance.poolParentDic[prefab]);
Instance.poolParentDic.Remove(prefab);
}
// ----- 获取池状态 -----
//是否已创建池
public static bool IsCreatPool<T>(T prefab) where T : Component
{
return IsCreatPool(prefab.gameObject);
}
public static bool IsCreatPool(GameObject prefab)
{
return Instance.idlePoolDic.ContainsKey(prefab);
}
//是否在对象池内
public static bool IsInPool<T>(T obj) where T : Component
{
return IsInPool(obj.gameObject);
}
public static bool IsInPool(GameObject obj)
{
return Instance.workItemDic.ContainsKey(obj);
}
//池内对象数量
public static int PoolIdleCount<T>(T prefab) where T : Component
{
return PoolIdleCount(prefab.gameObject);
}
public static int PoolIdleCount(GameObject prefab)
{
List<GameObject> list;
if (Instance.idlePoolDic.TryGetValue(prefab, out list))
return list.Count;
return 0;
}
//池外对象数量
public static int PoolWorkCount<T>(T prefab) where T : Component
{
return PoolWorkCount(prefab.gameObject);
}
public static int PoolWorkCount(GameObject prefab)
{
int count = 0;
foreach (var InstansePrefab in Instance.workItemDic.Values)
if (prefab == InstansePrefab)
count++;
return count;
}
//所有池内对象数量总和
public static int AllPoolIdleCount()
{
int count = 0;
foreach (List<GameObject> list in Instance.idlePoolDic.Values)
count += list.Count;
return count;
}
//所有池外对象数量总和
public static int AllPoolWorkCount()
{
return Instance.workItemDic.Count;
}
// -----
//获取池内所有对象
public static List<T> GetPoolIdleItem<T>(T prefab, List<T> list = null, bool appendList = true) where T : Component
{
if (list == null)
list = new List<T>();
if (!appendList)
list.Clear();
List<GameObject> pool;
if (Instance.idlePoolDic.TryGetValue(prefab.gameObject, out pool))
for (int i = 0; i < pool.Count; ++i)
list.Add(pool[i].GetComponent<T>());
return list;
}
public static List<GameObject> GetPoolIdleItem(GameObject prefab, List<GameObject> list = null, bool appendList = true)
{
if (list == null)
list = new List<GameObject>();
if (!appendList)
list.Clear();
List<GameObject> pool;
if (Instance.idlePoolDic.TryGetValue(prefab, out pool))
list.AddRange(pool);
return list;
}
//获取池外所有对象
public static List<T> GetPoolWorkItem<T>(T prefab, List<T> list = null, bool appendList = true) where T : Component
{
if (list == null)
list = new List<T>();
if (!appendList)
list.Clear();
var prefabObj = prefab.gameObject;
foreach (var item in Instance.workItemDic)
if (item.Value == prefabObj)
list.Add(item.Key.GetComponent<T>());
return list;
}
public static List<GameObject> GetPoolWorkItem(GameObject prefab, List<GameObject> list = null, bool appendList = true)
{
if (list == null)
list = new List<GameObject>();
if (!appendList)
list.Clear();
foreach (var item in Instance.workItemDic)
if (item.Value == prefab)
list.Add(item.Key);
return list;
}
}
利用This再封装,这一部分都是重复代码,可忽略,目的就是将对象池的方法,利用This进行静态封装,方便使用时调用。
public static class GenericPoolHelper
{
public static void CreatePool<T>(this T prefab, int initialPoolSize = 0) where T : Component
{
GenericPool.CreatePool(prefab, initialPoolSize);
}
public static void CreatePool(this GameObject prefab, int initialPoolSize = 0)
{
GenericPool.CreatePool(prefab, initialPoolSize);
}
public static T Create<T>(this T prefab) where T : Component
{
return GenericPool.Create(prefab, null, Vector3.zero, Quaternion.identity);
}
public static T Create<T>(this T prefab, Transform parent) where T : Component
{
return GenericPool.Create(prefab, parent, Vector3.zero, Quaternion.identity);
}
public static T Create<T>(this T prefab, Vector3 position) where T : Component
{
return GenericPool.Create(prefab, null, position, Quaternion.identity);
}
public static T Create<T>(this T prefab, Transform parent, Vector3 position) where T : Component
{
return GenericPool.Create(prefab, parent, position, Quaternion.identity);
}
public static T Create<T>(this T prefab, Vector3 position, Quaternion rotation) where T : Component
{
return GenericPool.Create(prefab, null, position, rotation);
}
public static T Create<T>(this T prefab, Transform parent, Vector3 position, Quaternion rotation) where T : Component
{
return GenericPool.Create(prefab, parent, position, rotation);
}
public static GameObject Create(this GameObject prefab)
{
return GenericPool.Create(prefab, null, Vector3.zero, Quaternion.identity);
}
public static GameObject Create(this GameObject prefab, Transform parent)
{
return GenericPool.Create(prefab, parent, Vector3.zero, Quaternion.identity);
}
public static GameObject Create(this GameObject prefab, Vector3 position)
{
return GenericPool.Create(prefab, null, position, Quaternion.identity);
}
public static GameObject Create(this GameObject prefab, Transform parent, Vector3 position)
{
return GenericPool.Create(prefab, parent, position, Quaternion.identity);
}
public static GameObject Create(this GameObject prefab, Vector3 position, Quaternion rotation)
{
return GenericPool.Create(prefab, null, position, rotation);
}
public static GameObject Create(this GameObject prefab, Transform parent, Vector3 position, Quaternion rotation)
{
return GenericPool.Create(prefab, parent, position, rotation);
}
public static void Reset<T>(this T obj) where T : Component
{
GenericPool.Reset(obj);
}
public static void Reset(this GameObject obj)
{
GenericPool.Reset(obj);
}
public static void ResetAll<T>(this T prefab) where T : Component
{
GenericPool.ResetAll(prefab);
}
public static void ResetAll(this GameObject prefab)
{
GenericPool.ResetAll(prefab);
}
public static void DestroyPoolIdle<T>(this T prefab) where T : Component
{
GenericPool.DestroyPoolIdle(prefab);
}
public static void DestroyPoolIdle(this GameObject prefab)
{
GenericPool.DestroyPoolIdle(prefab);
}
public static void DestroyPoolAll<T>(this T prefab) where T : Component
{
GenericPool.DestroyPoolAll(prefab);
}
public static void DestroyPoolAll(this GameObject prefab)
{
GenericPool.DestroyPoolAll(prefab);
}
public static bool IsCreatPool<T>(this T prefab) where T : Component
{
return GenericPool.IsCreatPool(prefab);
}
public static bool IsCreatPool(this GameObject prefab)
{
return GenericPool.IsCreatPool(prefab);
}
public static bool IsInPool<T>(this T obj) where T : Component
{
return GenericPool.IsInPool(obj);
}
public static bool IsInPool(this GameObject obj)
{
return GenericPool.IsInPool(obj);
}
public static int PoolIdleCount<T>(this T prefab) where T : Component
{
return GenericPool.PoolIdleCount(prefab);
}
public static int PoolIdleCount(this GameObject prefab)
{
return GenericPool.PoolIdleCount(prefab);
}
public static int PoolWorkCount<T>(this T prefab) where T : Component
{
return GenericPool.PoolWorkCount(prefab);
}
public static int PoolWorkCount(this GameObject prefab)
{
return GenericPool.PoolWorkCount(prefab);
}
public static List<T> GetPoolIdleItem<T>(this T prefab, List<T> list = null, bool appendList = true) where T : Component
{
return GenericPool.GetPoolIdleItem(prefab, list, appendList);
}
public static List<GameObject> GetPoolIdleItem(this GameObject prefab, List<GameObject> list = null, bool appendList = true)
{
return GenericPool.GetPoolIdleItem(prefab, list, appendList);
}
public static List<T> GetPoolWorkItem<T>(this T prefab, List<T> list = null, bool appendList = true) where T : Component
{
return GenericPool.GetPoolWorkItem(prefab, list, appendList);
}
public static List<GameObject> GetPoolWorkItem(this GameObject prefab, List<GameObject> list = null, bool appendList = true)
{
return GenericPool.GetPoolWorkItem(prefab, list, appendList);
}
}