diff --git a/Assets/_Game/Scripts/Combat/HitBox.cs b/Assets/_Game/Scripts/Combat/HitBox.cs index 2cb1b7f..54929f8 100644 --- a/Assets/_Game/Scripts/Combat/HitBox.cs +++ b/Assets/_Game/Scripts/Combat/HitBox.cs @@ -86,6 +86,8 @@ namespace BaseGames.Combat /// public void Activate(DamageSourceSO source = null, Transform attacker = null) { + // 保证碰撞体已收集(防止 Activate 早于 Awake 调用时对空列表启用碰撞体) + EnsureInitialized(); _currentActivationId = _nextActivationId++; _currentSource = source ?? _defaultSource; _attackerTransform = attacker ?? transform; @@ -115,8 +117,21 @@ namespace BaseGames.Combat if (source != null) _currentSource = source; } - private void Awake() + // 懒初始化标记:保证碰撞体收集只做一次,且不被 Awake / Activate 的调用顺序影响 + private bool _initialized; + + private void Awake() => EnsureInitialized(); + + /// + /// 懒初始化:收集直属碰撞体 / 子代理 / 服务缓存,并将碰撞体置为禁用(默认关闭)。 + /// Awake 与 Activate 都会调用——保证即使某组件(如 BodyContactDamage)因脚本执行顺序 + /// 在本组件 Awake 之前就调用 Activate(),碰撞体列表也已就绪。否则 Activate 会对空列表 + /// 启用碰撞体、随后 Awake 再把碰撞体禁用,导致判定盒永久收不到 Trigger 事件。 + /// + private void EnsureInitialized() { + if (_initialized) return; + _initialized = true; // 收集本节点上所有直属 Collider2D,并验证 isTrigger _directColliders = GetComponents(); foreach (var col in _directColliders)