13. 对象池
1.02. 创建房间的 Prefab2.03. 设计地图配置表3.04. 生成地图上的房间4.07. 泛型事件框架5.08. 场景加载6.09. 保存地图场景7.10. 房间进出逻辑8.11. 制作卡牌 Prefab9.12. 创建卡牌数据类
10.13. 对象池
11.14. 制作卡牌库实现抽卡12.15. 创建卡牌布局13.16. 抽卡动画14.17. 实现卡牌扇形布局15.18. 实现鼠标事件16.19. 卡牌拖拽17.20. 攻击牌的拖拽指针18.21. 实现洗牌逻辑19.22. 导入Spine人物素材20.23. 人物基类代码21.24. 执行卡牌效果22.25. 制作血条的 UI Document23.26. 绑定血条数据24.27. 创建USS血条样式25.28. 制作 Gameplay Panel26.29. 绑定 Gameplay Panel 数据27.30. 回合转换28.31. 出牌能量判断29.32. 防御牌及 UI30.33. 回血的苹果牌及特效31.34. 增加力量牌及 UI32.35. 更多卡牌33.36. 人物动画34.37. 敌人意图 AI 逻辑35.38. 敌人的动画执行逻辑36.39. 对战胜负逻辑37.40. 制作胜利和抽卡面板38.41. 抽卡面板的实际逻辑39.42. GameOver 及 Menu 面板40.43. 实现休息房间的逻辑41.44. Boss 制作和整体流程42.45. 淡入淡出及打包游戏创建对象池
我们后面会创建出很多的卡牌,如果每张卡牌都需要 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
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?