13. 对象池
创建对象池
我们后面会创建出很多的卡牌,如果每张卡牌都需要 Instantiate 和 Destroy 的话,就会非常消耗性能。因此我们使用对象池来管理这些对象,使它们的分配和开销减少
具体代码如下
using System.Diagnostics.Tracing;
using UnityEngine;
using UnityEngine.Pool;
public class PoolTool : MonoBehaviour
{
public GameObject objPrefab;
private ObjectPool<GameObject> pool;
private void Start()
{
// 初始化对象池
pool = new ObjectPool<GameObject>(
createFunc: () => Instantiate(objPrefab, transform),
actionOnGet: (obj) => obj.SetActive(true),
actionOnRelease: (obj) => obj.SetActive(false),
actionOnDestroy: (obj) => Destroy(obj),
// 是否检查我们的对象
collectionCheck: false,
defaultCapacity: 10,
maxSize: 20
);
PreFillPool(7);
}
private void PreFillPool(int count)
{
var preFillArray = new GameObject[count];
for (int i = 0; i < count; i++)
{
preFillArray[i] = pool.Get();
}
foreach (var item in preFillArray)
{
pool.Release(item);
}
}
public GameObject GetObjectFromPool()
{
return pool.Get();
}
public void ReleaseObjectToPool(GameObject obj)
{
pool.Release(obj);
}
}
在这段代码中,我们使用 new ObjectPool 新建了一个对象池。它创建新对象的时候使用Instantiate
,从对象池获取对象的时候使用SetActive(true)
,将对象释放到对象池的时候使用SetActive(false)
,销毁对象使用Destroy
。同时还指定,不检查对象,默认大小是10,最大大小是20
对象池一开始是不会分配对象的,所以我们需要在 Start 的时候先手动分配一些对象,并把它们返回到对象池中。这就是PreFillPool
的实现方式
为了别人可以方便使用 PoolTool,所以我们需要开放两个接口GetObjectFromPool
和ReleaseObjectToPool
,用于从对象池中获取对象,以及将对象返回到对象池中
卡牌管理器
对象池里面现在拥有的对象都是空白的对象,需要给它们进行赋值,这就是 CardManager 的工作了
CardManager 会从 Addressable 中读取所有卡牌类型,然后将它们保存到 cardDataList 中
请注意Addressables.LoadAssetsAsync<CardDataSO>("CardData", null)
,这句话的意思是读取 Addressable 中 key 为CardData
的数据,因此我们需要将之前做的防御牌变成 Addressable
然后把它的标签改成CardData
运行检查结果
对象池成功分配了 7 张卡牌
卡牌管理器成功读到了 CardDataSO