首页/ 第 16 章 · 性能优化/ 第 269 课
LESSON 269 · 性能优化

对象池实战(完整系统)

对象池系统完成。下一课做 LOD 与遮挡剔除实战。

⏱ 约 15 分钟📊 难度:入门🗂 第 16 章 · 性能优化📍 第 269 / 300 课
课程进度
269 / 300

🎯本节学习目标

  • 实现通用对象池
  • 实现自动扩容
  • 接入游戏场景

🚀课程导读

第 198/215 课用了简单对象池,本课做一个“通用、可复用的对象池系统”。

通用对象池设计

一个池管所有。

  1. 【设计】用 Dictionary 按预制体分池:
  2. public class ObjectPool : MonoBehaviour {
  3. public static ObjectPool Instance;
  4. private Dictionary<string, Queue<GameObject>> pools = new Dictionary<string, Queue<GameObject>>();
  5. void Awake() { Instance = this; }
  6. public GameObject Get(GameObject prefab, Vector3 pos, Quaternion rot) {
  7. string key = prefab.name;
  8. GameObject obj;
  9. if (pools.ContainsKey(key) && pools[key].Count > 0) {
  10. obj = pools[key].Dequeue();
  11. obj.transform.position = pos;
  12. obj.transform.rotation = rot;
  13. obj.SetActive(true);
  14. } else {
  15. obj = Instantiate(prefab, pos, rot);
  16. }
  17. return obj;
  18. }
  19. public void Release(GameObject obj, float delay = 0f) {
  20. if (delay <= 0f) { obj.SetActive(false); PoolIt(obj); }
  21. else StartCoroutine(ReleaseLater(obj, delay));
  22. }
  23. IEnumerator ReleaseLater(GameObject obj, float d) { yield return new WaitForSeconds(d); obj.SetActive(false); PoolIt(obj); }
  24. void PoolIt(GameObject obj) {
  25. string key = obj.name.Replace(“”(Clone)“
  26. ”“”);
  27. if (!pools.ContainsKey(key)) pools[key] = new Queue<GameObject>();
  28. pools[key].Enqueue(obj);
  29. }
  30. }
  31. 【自动扩容】池空时自动 Instantiate(else 分支)。
  32. 【注意】Release 时先 SetActive(false) 再入池。
  33. 【完成】通用池“上线”!
💡
通用对象池 = Dictionary 分池 + Get 复用/新建 + Release 回收。一套管所有。

接入实战

子弹、特效、敌人全走池。

  1. 【子弹】发射时:
  2. GameObject b = ObjectPool.Instance.Get(bulletPrefab, firePoint.position, firePoint.rotation);
  3. b.GetComponent<Bullet>().Init(dir);
  4. 命中/超时:ObjectPool.Instance.Release(b);
  5. 【特效】爆炸:Get(explosionPrefab, pos, rot) → 播放 → Release(explosion, 2f)(延时回收)。
  6. 【敌人】死亡:Get(死亡特效) + Release(敌人)。
  7. 【Init 重置】复用对象要重置状态:子弹 Init 重置速度/伤害;敌人重置 hp。
  8. 【场景切换】池对象跨场景会丢:DontDestroyOnLoad 挂 ObjectPool 或场景内重建(第 172 课)。
  9. 【调试】Profiler 看 GC Alloc 是否大幅下降。
  10. 【完成】游戏“零 GC”体验!
  11. 【注意】入池对象要复位(位置/旋转/active/组件状态)。
  12. 【推荐】所有高频物(子弹/粒子/敌人/飘字)一律对象池。
对象池接入 = Get(取)+ 初始化(重置)+ Release(还)。三行养成习惯。

常见错误与排查

错误:池化对象状态残留?
原因:没重置
解决:Get 时统一 Reset(位置/速度/hp/特效 Clear);Release 前也清状态。

动手练习

课后小任务(做出来才算真的学会)

  • 实现通用对象池系统
  • 子弹/特效全走池
  • 验证 GC 大幅下降

本节小结

对象池系统完成。下一课做 LOD 与遮挡剔除实战。

完成打卡后,主站会实时更新你的学习进度 🎯

← 上一课场景加载优化(异步)