用途
对象池通过复用 GameObject 而不是反复实例化(Instantiate)和销毁(Destroy),减少 GC 压力并提升性能。适用于任何高频实例化的场景。
何时使用
- 频繁生成的对象(子弹、粒子、敌人)
- UI 列表项
- 音频源
- 网络消息
- 任何高频实例化
主要能力
基础对象池
提供泛型池实现 ObjectPool<T>,包含创建、获取、释放、销毁回调,支持默认容量与最大容量,并在构造时预热池。暴露 CountActive、CountInactive、CountAll 统计属性。
Unity 内置池(2021+)
使用 UnityEngine.Pool 命名空间下的 ObjectPool<T>,通过 createFunc、actionOnGet、actionOnRelease、actionOnDestroy 回调构建,支持 collectionCheck、defaultCapacity、maxSize 参数。示例展示子弹生成器 ProjectileSpawner。
池化对象基类
PooledObject<T> 抽象基类持有 IObjectPool<T> 引用,提供 SetPool、ReturnToPool 方法以及可重写的 OnSpawn、OnDespawn 钩子,便于在生成与回收时重置状态。
多预制体池
PoolManager 单例使用字典维护 GameObject -> ObjectPool<GameObject> 映射,提供 Spawn、Despawn、PrewarmPool 方法,并为每个预制体创建独立的父节点组织层级。配套 PoolExtensions 扩展方法提供 SpawnPooled 与 DespawnPooled 语法糖。
组件池
ComponentPool<T> 针对 Component 类型封装池,适用于 UI 伤害数字等场景,示例为 DamageNumberPool。
集合池
ListPool<T>:池化List<T>,提供GetDisposable返回可using的PooledList<T>结构体,作用域结束自动归还。StringBuilderPool:池化StringBuilder,提供GetStringAndRelease便捷方法。
音频池
AudioPool 池化 AudioSource,PlayOneShot 播放后通过协程在音频时长结束后自动归还。
性能考量
- 预热策略:
PoolWarmer在加载时按配置预热池,数量较大时分帧执行。 - 池统计:
PoolStats记录 Gets、Releases、Creates,计算命中率并输出日志。
使用方式
代码示例展示了从创建池、获取对象、释放对象到扩展方法调用的完整流程。核心模式为:创建时 SetActive(false),获取时 SetActive(true),释放时重置状态并 SetActive(false)。
适用场景
子弹、粒子、敌人、UI 列表项、伤害数字、音频源、网络消息等高频实例化对象。
限制与注意事项
- 需设置合理的最大容量,避免池无限增长。
- 应在释放时重置状态,而非获取时。
- 场景切换时需清理池以释放内存。
- 需跟踪预制体到池的映射,避免使用错误的池。
- 对象未重置时需实现
OnDespawn/Reset。 - 生成时对象仍处于激活状态时,应在创建回调而非获取回调中设置
SetActive。
最佳实践
- 在加载界面预热池
- 设置合适的最大容量
- 在释放时重置状态
- 使用组合(PooledObject 基类)
- 跟踪池命中率以优化容量
- 在
OnDisable中释放以处理场景切换 - 将非激活对象置于父节点下以组织层级
- 可用时使用内置池(2021+)
- 池化昂贵组件(粒子系统、音频)
- 通过性能分析验证 GC 改善