简介
什么是对象池?顾名思义,就是存放实例对象的池子,即缓冲区。一般对象池在初始化时会包含着若干个实例对象,当我们需要时便从池子里取出来,当不需要时便放回对象池里面。使用对象池不需要频繁的产生和销毁实例对象,当对象池中的实例对象不够用时才会继续产生实例对象,这大大的节省了性能。所以在很多频繁使用实例对象的场景中,我们常常可以看到对象池的身影,比如数据库连接池、线程池、任务队列池和大量的游戏场景。
PoolManager
我在空余时间写了一个unity的对象池管理PoolManager,除了实现了一般对象池功能,还对其做出了拓展,比如自动回收,自动删除长时间没用的对象,实例对象数量的限制等等,大家可以根据自己项目的需求对代码进行修改和拓展。
// <Licensing>
// Copyright (C) XM.All Rights Reserved.
// Author: 吴肖牧(XM)
// Date: 2019-03-26
// Desc: 对象池管理器
// <Licensing>
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XMFramework;
public class PoolManager : GameBase
{
private Dictionary<string, SpawnPool> _pools = new Dictionary<string, SpawnPool>();
public Dictionary<string, SpawnPool> GetPools()
{
return _pools;
}
public bool CreatePool(string poolName)
{
if (_pools.TryGetValue(poolName, out SpawnPool spawnPool))
{
XMDebug.Log("已存在对象池", poolName);
return false;
}
SpawnPool pool = new GameObject(poolName + "Pool").AddComponent<SpawnPool>();
pool.transform.SetParent(transform);
pool.poolName = poolName;
_pools.Add(poolName, pool);
return true;
}
public bool RemovePool(string poolName)
{
if (!_pools.TryGetValue(poolName, out SpawnPool spawnPool))
{
XMDebug.Log("找不到对象池", poolName);
return false;
}
spawnPool.Clean();
Destroy(spawnPool.gameObject);
_pools.Remove(spawnPool.poolName);
Util.ClearMemory();
return true;
}
public bool RemovePool(SpawnPool spawnPool)
{
if (ContainsValue(spawnPool))
{
spawnPool.Clean();
Destroy(spawnPool.gameObject);
_pools.Remove(spawnPool.poolName);
Util.ClearMemory();
return true;
}
else
{
XMDebug.Log("找不到对象池", spawnPool.poolName);
return false;
}
}
public SpawnPool GetSpawnPool(string poolName)
{
if (!_pools.TryGetValue(poolName, out SpawnPool spawnPool))
{
XMDebug.Log("找不到对象池", poolName);
return null;
}
return _pools[poolName];
}
public bool ContainsKey(string poolName)
{
return _pools.ContainsKey(poolName);
}
public bool ContainsValue(SpawnPool pool)
{
return _pools.ContainsValue(pool);
}
public void CleanPool()
{
foreach (KeyValuePair<string, SpawnPool> pair in _pools)
{
if (pair.Value.gameObject)
{
Destroy(pair.Value.gameObject);
}
}
_pools.Clear();
Util.ClearMemory();
}
}
// <Licensing>
// Copyright (C) XM.All Rights Reserved.
// Author: 吴肖牧(XM)
// Date: 2019-04-02
// Desc: 对象池生产器
// <Licensing>
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XMFramework;
public class SpawnPool : GameBase
{
public string poolName = "";
[SerializeField]
private List<PrefabPool> _prefabPools = new List<PrefabPool>();
private List<Transform> _spawned = new List<Transform>();//存放所有对象,暂时没用到
#region Prefab
public void AddPrefab(PrefabPool prefabPool)
{
if (_prefabPools.Contains(prefabPool))
{
XMDebug.Log("已存在对象", prefabPool);
return;
}
prefabPool.prefabScale = prefabPool.prefab.localScale;
_prefabPools.Add(prefabPool);
if (prefabPool.initDespawnCount > 0)
{
for (int i = 0; i < prefabPool.initDespawnCount; i++)
{
Transform inst = Instantiate<Transform>(prefabPool.prefab, Vector3.zero, Quaternion.identity, transform);
prefabPool._despawned.Add(inst);
inst.name = inst.name.Replace("(Clone)", "");
inst.gameObject.SetActive(false);
}
}
StartCoroutine(TidyDespawn(prefabPool));
}
public void DelPrefab(PrefabPool prefabPool)
{
if (_prefabPools.Contains(prefabPool))
{
_prefabPools.Remove(prefabPool);
}
else
{
XMDebug.Log("找不到对象", prefabPool);
}
}
#endregion
#region SpawnPrefab
public Transform Spawn(Transform prefab)
{
return Spawn(prefab, Vector3.zero, Quaternion.identity);
}
public Transform Spawn(Transform prefab, Transform parent)
{
return Spawn(prefab, Vector3.zero, Quaternion.identity, parent);
}
public Transform Spawn(Transform prefab, Vector3 pos, Quaternion rot)
{
Transform inst = Spawn(prefab, pos, rot, transform);
if (inst == null) return null;
return inst;
}
public Transform Spawn(Transform prefab, Vector3 pos, Quaternion rot, Transform parent)
{
Transform inst = Spawn(prefab.name, pos, rot, parent);
return inst;
}
#endregion
#region SpawnPrefabName
public Transform Spawn(string prefabName)
{
return Spawn(prefabName, Vector3.zero, Quaternion.identity);
}
public Transform Spawn(string prefabName, Transform parent)
{
return Spawn(prefabName, Vector3.zero, Quaternion.identity, parent);
}
public Transform Spawn(string prefabName, Vector3 pos, Quaternion rot)
{
Transform inst = Spawn(prefabName, pos, rot, transform);
if (inst == null) return null;
return inst;
}
public Transform Spawn(string prefabName, Vector3 pos, Quaternion rot, Transform parent)
{
Transform inst = null;
for (int i = 0; i < _prefabPools.Count; i++)
{
PrefabPool prefabPool = _prefabPools[i];
if (prefabPool.prefab.name == prefabName)
{
if (prefabPool.spawnMaxLimit > 0 && prefabPool._spawned.Count >= prefabPool.spawnMaxLimit)
{
return null;
}
if (prefabPool._despawned.Count > 0)
{
inst = prefabPool._despawned[0];
prefabPool._despawned.RemoveAt(0);
inst.gameObject.SetActive(true);
}
else
{
inst = Instantiate<Transform>(prefabPool.prefab, pos, rot, parent);
inst.name = inst.name.Replace("(Clone)", "");
}
prefabPool._spawned.Add(inst);
if (prefabPool.autoDespawnTime > 0)
{
StartCoroutine(AutoDespawn(inst, prefabPool.autoDespawnTime));
}
break;
}
}
if (inst == null) return null;
_spawned.Add(inst);
return inst;
}
#endregion
#region Despawn
/// <summary>
/// 销毁对象,销毁传的对象
/// </summary>
/// <param name="prefab">对象</param>
public void Despawn(Transform prefab)
{
if (prefab == null)
{
return;
}
Transform inst = null;
for (int i = 0; i < _prefabPools.Count; i++)
{
PrefabPool prefabPool = _prefabPools[i];
if (prefabPool.prefab.name == prefab.name)
{
if (prefabPool._spawned.Count > 0)
{
if (prefabPool._spawned.Contains(prefab))
{
inst = prefab;
if (prefabPool.despawnMaxLimit != 0)
{
if (prefabPool._despawned.Count < prefabPool.despawnMaxLimit)
{
prefabPool._despawned.Add(inst);
if (inst.parent != transform)
{
inst.SetParent(transform);
}
if (inst.localScale != prefabPool.prefabScale)
{
inst.localScale = prefabPool.prefabScale;
}
inst.gameObject.SetActive(false);
}
else
{
Destroy(inst.gameObject);
}
}
else
{
prefabPool._despawned.Add(inst);
if (inst.parent != transform)
{
inst.SetParent(transform);
}
if (inst.localScale != prefabPool.prefabScale)
{
inst.localScale = prefabPool.prefabScale;
}
inst.gameObject.SetActive(false);
}
prefabPool._spawned.Remove(inst);
}
}
break;
}
}
if (inst == null) return;
_spawned.Remove(inst);
}
/// <summary>
/// 销毁对象,销毁最不常用的对象
/// </summary>
/// <param name="prefabName">对象名字</param>
public void Despawn(string prefabName)
{
Transform inst = null;
for (int i = 0; i < _prefabPools.Count; i++)
{
PrefabPool prefabPool = _prefabPools[i];
if (prefabPool.prefab.name == prefabName)
{
if (prefabPool._spawned.Count > 0)
{
inst = prefabPool._spawned[0];
if (inst)
{
if (prefabPool.despawnMaxLimit != 0)
{
if (prefabPool._despawned.Count < prefabPool.despawnMaxLimit)
{
prefabPool._despawned.Add(inst);
if (inst.parent != transform)
{
inst.SetParent(transform);
}
if (inst.localScale != prefabPool.prefabScale)
{
inst.localScale = prefabPool.prefabScale;
}
inst.gameObject.SetActive(false);
}
else
{
Destroy(inst.gameObject);
}
}
else
{
prefabPool._despawned.Add(inst);
if (inst.parent != transform)
{
inst.SetParent(transform);
}
if (inst.localScale != prefabPool.prefabScale)
{
inst.localScale = prefabPool.prefabScale;
}
inst.gameObject.SetActive(false);
}
prefabPool._spawned.Remove(inst);
}
}
break;
}
}
if (inst == null) return;
_spawned.Remove(inst);
}
/// <summary>
/// 自动销毁对象
/// </summary>
/// <param name="inst"></param>
/// <param name="autoDespawnTime"></param>
/// <returns></returns>
private IEnumerator AutoDespawn(Transform inst, float autoDespawnTime)
{
yield return new WaitForSeconds(autoDespawnTime);
Despawn(inst);
}
/// <summary>
/// 自动整理销毁对象列表
/// </summary>
/// <param name="prefabPool"></param>
/// <returns></returns>
private IEnumerator TidyDespawn(PrefabPool prefabPool)
{
yield return new WaitForSeconds(prefabPool.tidyDespawnTime);
for (int i = 0; i < prefabPool.tidyCount; i++)
{
if (prefabPool._despawned.Count > prefabPool.tidyDespawnMinCount)
{
if (prefabPool._despawned[0])
{
Destroy(prefabPool._despawned[0].gameObject);
prefabPool._despawned.RemoveAt(0);
}
}
else
{
break;
}
}
StartCoroutine(TidyDespawn(prefabPool));
}
/// <summary>
/// 销毁所有对象
/// </summary>
public void DespawnAll()
{
for (int i = 0; i < _prefabPools.Count; i++)
{
PrefabPool prefabPool = _prefabPools[i];
for (int j = 0; j < prefabPool._spawned.Count; j++)
{
Transform inst = prefabPool._spawned[j];
if (inst)
{
prefabPool._despawned.Add(inst);
if (inst.parent != transform)
{
inst.SetParent(transform);
}
if (inst.localScale != prefabPool.prefabScale)
{
inst.localScale = prefabPool.prefabScale;
}
inst.gameObject.SetActive(false);
}
}
prefabPool._spawned.Clear();
}
_spawned.Clear();
}
/// <summary>
/// 清空所有对象
/// </summary>
public void Clean()
{
StopAllCoroutines();
for (int i = 0; i < _prefabPools.Count; i++)
{
PrefabPool prefabPool = _prefabPools[i];
for (int j = 0; j < prefabPool._spawned.Count; j++)
{
Transform inst = prefabPool._spawned[j];
if (inst)
{
Destroy(inst.gameObject);
}
}
prefabPool._spawned.Clear();
for (int j = 0; j < prefabPool._despawned.Count; j++)
{
Transform inst = prefabPool._despawned[j];
if (inst)
{
Destroy(inst.gameObject);
}
}
prefabPool._despawned.Clear();
}
_spawned.Clear();
}
#endregion
}
[System.Serializable]
public class PrefabPool
{
public Transform prefab;//对象池对象
public int initDespawnCount;//初始化数量
public int spawnMaxLimit;//生成最多限制数量
public float autoDespawnTime;//自动销毁时间,单位秒
public int despawnMaxLimit;//销毁对象列表最多限制数量
public float tidyDespawnTime;//自动整理销毁对象时间频率,单位秒
public int tidyDespawnMinCount;//自动整理销毁对象列表最少限制数量
public int tidyCount; //每次整理销毁对象数量
[HideInInspector]
public Vector3 prefabScale;//预设原大小,用于返回对象池重置大小
public PrefabPool(){ }
/// <summary>
/// 初始化对象池
/// </summary>
/// <param name="prefab">对象</param>
/// <param name="initDespawnCount">初始化隐藏的对象</param>
/// <param name="spawnMaxLimit">生成最多限制数量</param>
/// <param name="autoDespawnTime">自动销毁时间,单位秒</param>
/// <param name="despawnMaxLimit">销毁对象列表最多限制数量</param>
/// <param name="tidyDespawnTime">自动整理销毁对象时间频率,单位秒</param>
/// <param name="despawnMinLimit">自动整理销毁对象列表最少限制数量</param>
/// <param name="tidyCount">每次整理销毁对象数量</param>
public PrefabPool(Transform prefab, int initDespawnCount = 0, int spawnMaxLimit = 0, float autoDespawnTime = 0, int despawnMaxLimit = 0,
float tidyDespawnTime = 0, int despawnMinLimit = 0, int tidyCount = 0)
{
this.prefab = prefab;
this.initDespawnCount = initDespawnCount;
this.spawnMaxLimit = spawnMaxLimit;
this.autoDespawnTime = autoDespawnTime;
this.despawnMaxLimit = despawnMaxLimit;
this.tidyDespawnTime = tidyDespawnTime;
this.tidyDespawnMinCount = despawnMinLimit;
this.tidyCount = tidyCount;
}
/// <summary>
/// 生成的对象
/// </summary>
public List<Transform> _spawned = new List<Transform>();
/// <summary>
/// 销毁生成的对象
/// </summary>
public List<Transform> _despawned = new List<Transform>();
}
使用方式:
ResManager.Load("GameObjects", "PoolItem", (go) => {
if (PoolManager.CreatePool("Test"))
{
GameObject tr = go as GameObject;
item = tr.transform;
spawnPool = PoolManager.GetSpawnPool("Test");
PrefabPool prefabPool = new PrefabPool(item, 10, 12, 0, 20, 5, 4, 3);
spawnPool.AddPrefab(prefabPool);
}
});