using System.Collections.Generic; using UnityEngine; namespace BaseGames.Combat { /// /// HurtBox 所有者保护组件。防止同一角色身上的多个 HurtBox 在同一次 HitBox 激活中被重复伤害。 /// /// 工作原理:每次 HitBox 激活携带唯一 ActivationId(由 HitBox.Activate() 生成递增值)。 /// HurtBox.ReceiveDamage 调用 TryRegisterHit(id) 时,同一 id 只有首次调用返回 true; /// 后续同 id 调用(来自同一角色的其他 HurtBox 子节点)返回 false 并跳过伤害流水线, /// 从而保证"多个 HurtBox 共享同一 HP 池时,一次攻击只扣一次血"。 /// /// 生命周期:由 HurtBox.Awake() 在角色根节点自动添加(如不存在则创建)。无需手动挂载。 /// 逐帧通过 frameCount 差异懒清空处理集,零 GC 开销。 /// [AddComponentMenu("")] // 隐藏菜单:由 HurtBox 自动管理 public sealed class HurtBoxOwnerGuard : MonoBehaviour { private readonly HashSet _processedIds = new(4); private int _lastClearFrame = -1; /// /// 尝试注册一次命中。 /// /// HitBox 激活 ID(0 = 无追踪路径,始终允许通过)。 /// true = 首次注册,应继续处理伤害;false = 同 id 已被处理,跳过。 public bool TryRegisterHit(uint activationId) { // activationId == 0:LethalTrap / BodyContactDamage 等旁路路径,不做去重 if (activationId == 0) return true; EnsureClearedThisFrame(); return _processedIds.Add(activationId); } private void EnsureClearedThisFrame() { int frame = Time.frameCount; if (frame == _lastClearFrame) return; _processedIds.Clear(); _lastClearFrame = frame; } } }