【一元管理オブジェクトプール】
オブジェクト プールを統一的に管理するには、初期化、オブジェクトの貸し出し、オブジェクトのリサイクル、オブジェクト プールの増加、オブジェクト プールの削減、およびオブジェクト プールのクリアのメソッドを提供するのが比較的簡単です。
【コード】
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. 非同期読み込みメソッドを追加する