
joywayerandClaude Opus 5
1e3c060c8d
fix(core): 对象池真正通知 IPoolable,复用的敌人不再以死亡状态出场
IPoolable 的接口文档写着「由 PooledObject 子类或同 GameObject 上的其他
MonoBehaviour 实现,并在 PooledObject.OnSpawn/OnDespawn 中手动驱动」,
但那两个方法是空的 public virtual,全库无任何 PooledObject 子类,
GlobalObjectPool 也从不查找 IPoolable 组件——这份契约从未生效过。
全库 .OnSpawn(/.OnDespawn( 的调用点只有 4 处,真正驱动 EnemyBase
(唯一的 IPoolable 实现者)的只有 EnemyRespawner 一处手动补调。后果:
- EnemyBase.OnDespawn 在生产中从未被调用,其中的 _nav?.Stop() 是死代码;
- 更严重的是取出侧:PerformDeath 会 ForceState(Dead) 并禁用全部碰撞体后归池,
而 EnemySpawnerOnEvent / ChaoFengBoss 召唤 / RangedEnemy 这些取用方
没有补调 OnSpawn,拿到的复用敌人仍停在 Dead 态、碰撞体全关、HP 为 0——
一个不可交互也不会动的幽灵。EnemyRespawner 路径侥幸没暴露,只因为它手动补了。
修法是让池履行它自己声明的契约,而不是让各调用方继续手动补调:
PooledObject.OnSpawn/OnDespawn 转发给本物体上的 IPoolable。只扫本物体、
不向下扫子物体——接口文档限定的就是「同 GameObject」,向下扫会让嵌套的
可池化对象被两个 PooledObject 各通知一次。组件集惰性解析一次并缓存
(池化本就是为省开销,不能每次进出都遍历组件)。
同时统一两条归池路径的顺序:GlobalObjectPool.Despawn 原本先 SetActive(false)
再 OnDespawn,而 PooledObject.ForceReturnToPool 是反过来的。转发接通后这个
顺序就成了可观察行为,两条路径必须给出同一份契约——统一为「先通知再停用」,
清理才跑在还活跃的对象上。
EnemyRespawner 那次手动 OnSpawn 随之改为只在兜底实例化路径调用:池化路径
现在由转发完成,重复调用会让 OnSpawn 末尾的 Spawned?.Invoke() 触发两次,
即重复执行出生能力。(今天重复触发会被 Execute() 的 !_isRunning 门挡住,
但那是运气不是设计。)
验证:编译 0 错;EditMode 273/273(269 + 新增 4)。
分阶段观察过失败面:只加转发时,2 条转发测试转绿、顺序测试仍红在
WasActiveOnDespawn 上;补顺序后全绿。
变异验证——把扫描范围改成 GetComponentsInChildren 后,边界测试恰好变红
(该测试在修复前是平凡通过的,需确认它真有约束力),还原后复验 273/273。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-31 16:03:57 +08:00
..
2026-07-31 16:03:57 +08:00
2026-07-21 16:31:44 +08:00
2026-05-15 14:47:24 +08:00
2026-05-23 08:48:48 +08:00
2026-05-15 14:47:24 +08:00
2026-05-27 16:33:15 +08:00
2026-06-09 10:41:43 +08:00
2026-05-23 08:48:48 +08:00
2026-05-22 13:25:40 +08:00
2026-05-22 15:07:43 +08:00
2026-07-31 16:03:57 +08:00
2026-06-06 09:00:11 +08:00
2026-05-08 11:04:00 +08:00
2026-05-15 14:47:24 +08:00
2026-05-08 11:04:00 +08:00
2026-05-15 14:47:24 +08:00
2026-05-15 14:47:24 +08:00
2026-05-08 11:04:00 +08:00
2026-05-23 08:48:48 +08:00
2026-05-15 14:47:24 +08:00
2026-05-08 11:04:00 +08:00
2026-05-08 11:04:00 +08:00
2026-06-05 18:41:33 +08:00
2026-05-23 08:48:48 +08:00
2026-05-08 11:04:00 +08:00
2026-05-15 14:47:24 +08:00
2026-05-13 09:19:54 +08:00
2026-05-15 14:47:24 +08:00
2026-05-08 11:04:00 +08:00
2026-05-08 11:04:00 +08:00
2026-05-08 11:04:00 +08:00