【统一管理对象池】
统一管理对象池,需要提供初始化、借出对象、回收对象、增加对象池、减少对象池、清空对象池的方法,比较简单。
【代码实现】
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
namespace Cache
{
public class ObjectPoolManager
{
private static ObjectPoolManager _instance;
public static ObjectPoolManager Instance
{
get
{
if (_instance == null)
_instance = new ObjectPoolManager();
return _instance;
}
}
public Dictionary<string, ObjectPoolBase> pools = new Dictionary<string, ObjectPoolBase>();
private Dictionary<int, string> lentInstance2Object = new Dictionary<int, string>();
private ObjectPoolAsset objectPoolAsset;
private string assetPath = "Assets/Resources/ObjectPoolAsset.asset";
#if UNITY_EDITOR
public void Awake()
{
objectPoolAsset = Resources.Load<ObjectPoolAsset>(assetPath);
if (objectPoolAsset == null)
{
objectPoolAsset = ScriptableObject.CreateInstance<ObjectPoolAsset>();
AssetDatabase.CreateAsset(objectPoolAsset, assetPath);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
}
#endif
public void InitPool()
{
#if !UNITY_EDITOR
objectPoolAsset = Resources.Load<ObjectPoolAsset>(assetPath);//不是Editor的情况下如何载入配置,这个可以根据需要自己写
#endif
foreach (PoolInfo poolInfo in objectPoolAsset.poolInfos)
{
AddPool(poolInfo);
}
}
public GameObject LendObjectOut(string poolName, string objectName, Transform parent = null, object[] extradata = null)
{
GameObject go = null;
if(!pools.ContainsKey(poolName))
{
Debug.LogWarning("该对象池不存在:" + poolName);
return null;
}
go = pools[poolName].LendObjectOut(objectName, parent, extradata);
if(go)
{
lentInstance2Object[go.GetInstanceID()] = poolName;
}
return go;
}
public bool RecycleObject(GameObject go)
{
if (go == null)
return false;
if (!lentInstance2Object.ContainsKey(go.GetInstanceID()))//表示不是从该对象池中借出的
return false;
return pools[lentInstance2Object[go.GetInstanceID()]].RecycleObject(go);
}
public bool AddPool(PoolInfo poolInfo)
{
if (pools.ContainsKey(poolInfo.poolName))
{
Debug.LogWarning("已包含该对象池:" + poolInfo.poolName);
return false;
}
switch (poolInfo.poolType)
{
case PoolType.Single:
pools.Add(poolInfo.poolName, new SingleObjectPool(poolInfo.capacity, poolInfo.poolName, poolInfo.expansionStrategy));
break;
case PoolType.Multi:
pools.Add(poolInfo.poolName, new MultiObjectPool(poolInfo));
break;
case PoolType.ObjectType:
pools.Add(poolInfo.poolName, new ObjectTypePool(poolInfo));
break;
case PoolType.StageType:
pools.Add(poolInfo.poolName, new StageObjectPool(poolInfo));
break;
case PoolType.NONE:
Debug.LogWarning("无效的对象池类型:" + poolInfo.poolName);
break;
}
return true;
}
public bool RemovePool(string poolName)
{
if (!pools.ContainsKey(poolName))
{
Debug.LogWarning("不存在该对象池:" + poolName);
return false;
}
ObjectPoolBase pool = pools[poolName];
pools.Remove(poolName);
pool.Dispose();
return true;
}
public void ClearPool()
{
foreach (var item in pools.Values)
{
item.Dispose();
}
pools.Clear();
lentInstance2Object.Clear();
}
}
}
【拓展】
1.扩展编辑器:保证在任意编辑ObjectPoolAsset.asset时,不会导致在InitPool()时报错,目前的代码里并没有控制。
2.减少内存:依靠lentInstance2Object来找到对象属于哪个池子,因为做了多层嵌套,会导致重复,可以给物体添加一个类来读取,就省去了lentInstance2Object。
3.全部用ObjectPoolBase来实现不同类型的对象池的自由组合
4.改用基于AA的加载方式来加载物体
5.添加异步加载的方法