diff --git a/Assets/_Game/Scripts/Animation/EnemyAnimationEvents.cs b/Assets/_Game/Scripts/Animation/EnemyAnimationEvents.cs
index ea0e9d95..ffa4c76b 100644
--- a/Assets/_Game/Scripts/Animation/EnemyAnimationEvents.cs
+++ b/Assets/_Game/Scripts/Animation/EnemyAnimationEvents.cs
@@ -2,6 +2,7 @@ using System;
using Animancer;
using BaseGames.Combat;
using BaseGames.Enemies;
+using BaseGames.Feedback;
using UnityEngine;
namespace BaseGames.Animation
@@ -9,10 +10,10 @@ namespace BaseGames.Animation
///
/// 敌人动画事件接收器(架构 §AnimationModule)。
/// 挂载于敌人 Prefab 根节点。负责将 Animancer 动画时间点回调路由到
- /// HitBox 激活、弹幕生成、嘶吼状态、二阶段切换等系统。
+ /// HitBox 激活、弹幕生成、嘶吼状态、二阶段切换、无敌帧、反馈等系统。
///
/// 使用方式:
- /// 1. 在 Inspector 中填充 _hitBoxes、_enemy。
+ /// 1. 在 Inspector 中填充 _hitBoxes、_hurtBox、_enemy。
/// 2. 将每条 ClipTransition + AnimationEventConfigSO 配对添加到 _bindings。
/// 3. Awake 中 AnimationEventBinder.Bind 自动完成注入。
///
@@ -30,16 +31,23 @@ namespace BaseGames.Animation
[Header("子系统引用")]
[SerializeField] private HitBox[] _hitBoxes;
+ [SerializeField] private HurtBox _hurtBox;
[SerializeField] private EnemyBase _enemy;
[Header("事件绑定(每个 Clip 对应一个配置资产)")]
[SerializeField] private EventBinding[] _bindings;
+ private IFeedbackPlayer _feedback;
+
private void Awake()
{
if (_enemy == null)
_enemy = GetComponentInParent();
+ // IFeedbackPlayer 由父层或同层实现(EnemyFeedback / NullFeedbackPlayer),与玩家侧同写法
+ _feedback = GetComponentInParent()
+ ?? NullFeedbackPlayer.Instance;
+
foreach (var b in _bindings)
AnimationEventBinder.Bind(b.clip, b.config, this);
}
@@ -59,6 +67,16 @@ namespace BaseGames.Animation
SetHitBoxActive(payload, false);
break;
+ // ── 无敌帧 ────────────────────────────────────────────────
+ // 时长由动画时间轴上两个事件的间距表达,不在代码里写常量。
+ case AnimationEventType.EnableIFrame:
+ _hurtBox?.SetInvincible(true);
+ break;
+
+ case AnimationEventType.DisableIFrame:
+ _hurtBox?.SetInvincible(false);
+ break;
+
// ── 弹幕 / 技能 ───────────────────────────────────────────
case AnimationEventType.SpawnProjectile:
_enemy?.SpawnProjectile(payload);
@@ -78,6 +96,18 @@ namespace BaseGames.Animation
_enemy?.TriggerPhaseTwo();
break;
+ // ── 通用反馈 ──────────────────────────────────────────────
+ // 音效预警:在起手帧播一段可辨识的音,让玩家提前缩小招式可能性。
+ case AnimationEventType.TriggerFeedback:
+ if (!string.IsNullOrEmpty(payload))
+ _feedback.TriggerPreset(payload);
+ break;
+
+ case AnimationEventType.PlaySFX:
+ if (!string.IsNullOrEmpty(payload))
+ _feedback.PlaySFXById(payload);
+ break;
+
// ── 状态机钩子 ────────────────────────────────────────────
case AnimationEventType.AnimationComplete:
_enemy?.OnAnimationComplete(payload);