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)