# 07 · 反馈系统 > **命名空间** `BaseGames.Feedback` > **所属文档集** [← 返回索引](./README.md) · [总览](./00_Overview.md) > **依赖** Feel v4.3 · `BaseGames.Core.Events` · `BaseGames.Combat` --- ## 目录 1. [设计原则](#1-设计原则) 2. [Feel MMF_Player 体系](#2-feel-mmf_player-体系) 3. [PlayerFeedback — 玩家反馈配置](#3-playerfeedback--玩家反馈配置) 4. [EnemyFeedback — 敌人反馈配置](#4-enemyfeedback--敌人反馈配置) 5. [时间管理:子弹时间集成](#5-时间管理子弹时间集成) 6. [镜头震动集成](#6-镜头震动集成) 7. [音效管理](#7-音效管理) 8. [粒子特效规范](#8-粒子特效规范) 9. [UI 反馈](#9-ui-反馈) 10. [事件频道驱动的全局反馈](#10-事件频道驱动的全局反馈) 11. [FeedbackConfigSO](#11-feedbackconfigso) 12. [编辑器友好设计](#12-编辑器友好设计) --- ## 1. 设计原则 - **零耦合**:所有反馈通过**事件频道**或 `UnityEvent` 触发,GameLogic 不直接调用 Feedback - **数据驱动**:每种反馈配置为独立 `MMF_Player` 资产,可在 Inspector 中调节,无需修改代码 - **分层设计**:本地反馈(HitBox 命中瞬间)→ 全局反馈(OnHitConfirmed 频道)→ 时间管理(ParrySuccess) - **像素风格适配**:优先使用 Shader 闪光(Flash)而非粒子,减少视觉噪声 --- ## 2. Feel MMF_Player 体系 ### MMF_Player 命名规范 所有 `MMF_Player` GameObject 命名格式:`MMF_{Owner}_{EventName}` 示例: - `MMF_Player_OnHit`(玩家受击) - `MMF_Player_OnAttackHit`(玩家攻击命中) - `MMF_Player_OnParrySuccess`(弹反成功) - `MMF_Enemy_OnHit`(敌人受击) - `MMF_Enemy_OnDeath`(敌人死亡) ### MMF_Player Feedback 类型速查 | Feel Feedback 类型 | 常用场景 | 关键参数 | |-------------------|---------|---------| | `MMF_Flash` | Sprite 受击白闪 | `FlashColor`, `Duration` | | `MMF_SpriteRenderer` | 闪烁/变色 | `Color`, `Blink Duration` | | `MMF_Particles` | 命中粒子特效 | `ParticleSystem` 引用 | | `MMF_AudioSource` | 播放音效 | `AudioClip`, `Volume`, `Pitch Variance` | | `MMF_CinemachineImpulse` | 镜头震动 | `ImpulseSource`, `Velocity` | | `MMF_FreezeFrame` | 命中冻帧 | `FreezeDuration` | | `MMF_TimeScale` | 子弹时间 | `TimeScale`, `Duration` | | `MMF_TextMeshPro` | 伤害数字弹出 | `Value`, `Animation Curve` | | `MMF_Position` | 物体位移(扑克震动)| `Displacement`, `Curve` | | `MMF_Scale` | 冲击缩放(南瓜弹)| `Scale`, `Duration` | | `MMF_Enable` | 启用/禁用 GameObject | `Target` | --- ## 3. IFeedbackPlayer 接口 — 反馈抽象层 为了让游戏逻辑(`PlayerCombat`、`EnemyBase`)与具体的 Feel/MMF_Player 实现零耦合,所有反馈调用必须通过 `IFeedbackPlayer` 接口进行: ```csharp /// /// 反馈执行器的抽象接口。 /// GameLogic 依赖此接口,而非具体的 MMF_Player 引用。 /// public interface IFeedbackPlayer { void PlayHit(HitWeight weight); // 命中反馈(轻/中/重) void PlayParrySuccess(); // 弹反成功 void PlayTakeHit(); // 玩家受击 void PlayDeath(); // 死亡演出 void PlayHeal(); // 治疗 void PlayLandImpact(); // 落地冲击 void PlayAttackWhoosh(); // 攻击挥动音效 void PlayJumpLaunch(); // 起跳 void TriggerPreset(string presetId); // 通过 ID 触发任意预设(动画事件用) void PlaySFXById(string sfxId); // 通过 ID 播放音效(动画事件用) } ``` **使用规范**: - `PlayerCombat`、`PlayerMovement` 等逻辑组件持有 `IFeedbackPlayer _feedback`(通过 Inspector 注入) - 测试时可替换为 `NullFeedbackPlayer`(空实现),完全不需要 Feel 资产 - 新增反馈类型时先在接口声明,再在 `PlayerFeedback` 中实现,保持单一变更点 --- ## 4. PlayerFeedback — 玩家反馈配置 `PlayerFeedback` 组件挂载在 Player Prefab 下,实现 `IFeedbackPlayer` 接口,聚合所有玩家相关 `MMF_Player`: ### 受击反馈(OnTakeHit) | Feedback | 参数 | 视觉效果 | |----------|------|---------| | `MMF_Flash` | 白色,0.15s | Sprite 白闪(经典受击感)| | `MMF_AudioSource` | SFX_Player_Hurt | 受伤音效(随机 Pitch 0.9~1.1)| | `MMF_CinemachineImpulse` | Medium,0.5强度 | 镜头震动 | | `MMF_FreezeFrame` | 0.033s | 2帧冻帧 | | `MMF_Position` | 朝击退反方向 1 unit | 玩家轻微弹开 | ### 攻击命中反馈(OnAttackHit) | Feedback | 参数 | 说明 | |----------|------|------| | `MMF_Particles` | HitSpark Prefab,命中点生成 | 金属火花粒子 | | `MMF_AudioSource` | SFX_Attack_Hit(随机 3 个变体之一)| 命中音效 | | `MMF_FreezeFrame` | 0.033s(2帧)| 命中停顿感 | | `MMF_CinemachineImpulse` | Light,0.2强度 | 轻微镜头震 | ### 弹反成功反馈(OnParrySuccess) | Feedback | 参数 | 说明 | |----------|------|------| | `MMF_Flash` | 金色,0.1s | Sprite 金光闪烁 | | `MMF_Particles` | ParryFlash Prefab(全屏金色光圈)| 弹反标志性特效 | | `MMF_AudioSource` | SFX_Parry_Success(金属碰撞音)| 清脆弹反音效 | | `MMF_CinemachineImpulse` | Parry,0.7强度,带方向 | 有方向性震动 | | `MMF_TimeScale` | 0.25×,0.2s | 子弹时间(与 ParrySystem 同步)| | `MMF_FreezeFrame` | 0.066s(4帧)| 更长冻帧强调击中感 | ### 治疗反馈(OnHeal) | Feedback | 参数 | 说明 | |----------|------|------| | `MMF_Flash` | 蓝色,0.2s | 恢复光效 | | `MMF_Particles` | HealParticle Prefab | 向上飘散的蓝色粒子 | | `MMF_AudioSource` | SFX_Heal | 回血音效 | ### 死亡反馈(OnDeath) | Feedback | 参数 | 说明 | |----------|------|------| | `MMF_AudioSource` | SFX_Player_Death | 死亡音效 | | `MMF_CinemachineImpulse` | Heavy,1.0强度 | 强烈震动 | | `MMF_FreezeFrame` | 0.1s(6帧)| 死亡冻帧 | | `MMF_Enable` | 禁用 HurtBox | 防止死亡后继续受击 | --- ## 4. EnemyFeedback — 敌人反馈配置 `EnemyFeedback` 挂在每个敌人 Prefab 下: ### 受击反馈(OnHit) | Feedback | 参数 | 说明 | |----------|------|------| | `MMF_Flash` | 白色,0.1s | 受击白闪 | | `MMF_AudioSource` | SFX_Enemy_Hurt(按敌人类型变体)| 受伤音效 | | `MMF_Particles` | HitSpark(命中位置)| 命中粒子 | ### 被弹反反馈(OnParried) | Feedback | 参数 | 说明 | |----------|------|------| | `MMF_Flash` | 金色,0.15s | 与玩家弹反视觉对应 | | `MMF_SpriteRenderer` | 扭曲/Shader 效果 | 硬直视觉反馈 | | `MMF_AudioSource` | SFX_Parry_Impact | 被弹反音效 | | `MMF_Position` | 小幅后退 | 轻微击退特效 | ### 死亡反馈(OnDeath) | Feedback | 参数 | 说明 | |----------|------|------| | `MMF_AudioSource` | SFX_Enemy_Death | 死亡音效 | | `MMF_Particles` | DeathParticle Prefab | 死亡解体粒子 | | `MMF_Enable` | 禁用 Rigidbody2D / Colliders | 防止尸体物理继续 | | `MMF_FreezeFrame` | 0.05s(3帧)| 击杀冻帧 | --- ## 5. 时间管理:子弹时间集成 子弹时间通过两套系统协调: ### Feel MMTimeManager(主要) - 注册所有 `MMTimeManager` Listener - `ParrySystem.TriggerParrySuccess()` → `MMTimeScaleEvent` 广播 - `MMTimeManager` 接收后修改 `Time.timeScale` - 时间恢复:Lerp 方式平滑还原(`LerpSpeed = 20`) ### 与 Animancer 的配合 - Animancer 动画默认使用 `Time.timeScale`(跟随子弹时间减速) - 特例:UI 动画、音频播放必须用 `Time.unscaledDeltaTime` - 检测敌人动画速率被子弹时间自动降低(无需额外配置) --- ## 6. 镜头震动集成 详见 [02_CameraSystem](./02_CameraSystem.md#6-镜头震动cinemachineimpulse)。 ### Feel 与 Cinemachine Impulse 的桥接 Feel `MMF_CinemachineImpulse` → 内部调用 `CinemachineImpulseSource.GenerateImpulse()` → `CinemachineImpulseListener` 响应。 **PlayerFeedback 中每种震动类型对应 ImpulseSource**(Inspector 中拖入引用): | 震动类型 | 来源 ImpulseSource | 说明 | |---------|-------------------|------| | Light | `ImpulseSource_Light` | 普通命中 | | Medium | `ImpulseSource_Medium` | 玩家受伤 | | Heavy | `ImpulseSource_Heavy` | 玩家死亡 / Boss 重击 | | Parry | `ImpulseSource_Parry` | 弹反成功(带方向性)| --- ## 7. 音效管理 ### 音效 SO 资产结构 `AudioEventSO` 封装音效播放参数(非特定 AudioSource),通过事件频道解耦: | 字段 | 类型 | 说明 | |------|------|------| | `Clips` | `AudioClip[]` | 随机选取其中一个播放 | | `Volume` | `float` | 基础音量(0~1)| | `PitchMin` | `float` | Pitch 随机范围最小值 | | `PitchMax` | `float` | Pitch 随机范围最大值 | | `MixerGroup` | `AudioMixerGroup` | SFX / Music / UI 混音组 | 所有 `MMF_AudioSource` 通过 `AudioEventSO` 播放音效(而非直接引用 `AudioClip`),实现随机音调变化。 ### 音效资产路径 ``` Assets/Audio/SFX/ ├── Player/ │ ├── SFX_Player_Hurt.asset │ ├── SFX_Player_Death.asset │ ├── SFX_Attack_Hit.asset ← 含3个变体Clip │ ├── SFX_Parry_Success.asset │ └── SFX_Heal.asset ├── Enemies/ │ ├── SFX_Enemy_Hurt_Generic.asset │ └── SFX_Enemy_Death_Generic.asset └── World/ ├── SFX_Footstep.asset └── SFX_Landing.asset ``` --- ## 8. 粒子特效规范 | 特效 Prefab | 触发来源 | 生命周期 | 说明 | |-------------|---------|---------|------| | `FX_HitSpark` | 攻击命中 | 0.3s 后自销毁 | 金属火花(4~6 粒子)| | `FX_ParryFlash` | 弹反成功 | 0.5s 后自销毁 | 金色光圈(全屏扩散)| | `FX_HealParticle` | 玩家治疗 | 1.0s 后自销毁 | 蓝色粒子上飘 | | `FX_EnemyDeath` | 敌人死亡 | 1.5s 后自销毁 | 解体粒子(按敌人主题色)| | `FX_DustCloud` | 玩家落地 | 0.5s 后自销毁 | 落地灰尘 | | `FX_DashTrail` | 玩家冲刺 | 0.4s 后自销毁 | 冲刺残影(Sprite Fade)| **像素风格适配**:所有粒子使用 `Render Mode: Billboard`,粒子贴图与角色 PPU(32 PPU)保持一致,避免模糊。 --- ## 9. UI 反馈 ### 伤害数字(FloatingText) - 触发:`OnHitConfirmed` 事件频道 - 从对象池中取 `FloatingText` Prefab,在命中位置生成 - 数字内容:`DamageInfo.FinalDamage` - 弹反反击:数字显示为金色 + 粗体(`FinalDamage` 为 3× 时额外标记) - 动画:向上飘 0.8s + 淡出 ### HP 血条动画 - `OnPlayerHPChanged` 事件频道驱动 - 满格 HP 以绿色实心显示,扣除部分以红色渐出动画表示(延迟 0.2s 开始缩短,视觉缓冲) ### Soul 槽动画 - `OnSoulChanged` 事件频道驱动 - 弹反成功 +33 时,Soul 槽显示**扫光动画**(金色高亮流过 1/3 槽) --- ## 10. 事件频道驱动的全局反馈 `GlobalFeedbackController` 组件(单例,挂在 `[Managers]` GO 上)监听全局频道并触发对应 `MMF_Player`: | 频道 | 触发反馈 | |------|---------| | `OnPlayerDied` | 停止音乐、播放死亡演出(慢慢音量淡出,画面泛红)| | `OnBossFightStarted` | 停止环境音乐、淡入 Boss 战BGM | | `OnBossFightEnded` | Boss 死亡演出(震动+特效+音乐过渡)| | `OnRoomEntered` | 淡出 → 淡入(场景切换遮罩)| --- ## 11. FeedbackConfigSO `FeedbackConfigSO` 全局配置,存放于 `Assets/ScriptableObjects/Config/FeedbackConfigSO.asset`: | 参数 | 类型 | 推荐值 | 说明 | |------|------|--------|------| | `HitFreezeFrames` | `int` | 2 | 命中冻帧帧数 | | `ParryFreezeFrames` | `int` | 4 | 弹反冻帧帧数 | | `SfxVolumeMaster` | `float` | 1.0 | SFX 总音量(0~1)| | `HapticsEnabled` | `bool` | true | 手柄震动开关(P2)| | `FloatingTextPoolSize` | `int` | 20 | 伤害数字对象池大小 | | `ParticlePoolSize` | `int` | 30 | 粒子特效对象池大小 | --- ## 12. 编辑器友好设计 ### MMF_Player 预览支持 Feel 原生支持在 Editor 非 Play Mode 下预览 `MMF_Player`: - Inspector 底部的"▶ Play"按钮可单独预览每组反馈 - `Preview in Editor` 模式下验证视觉效果,无需进入 Play Mode ### FX 对象池监控(Play Mode Inspector) ``` ┌─ GlobalFeedbackController ──────────────────────┐ │ FloatingText Pool: 14 / 20 available │ │ Particle Pool : 28 / 30 available │ │ ───────────────────────────────────────────── │ │ [Test: Player Hurt] [Test: Parry Success] │ │ [Test: Enemy Hit ] [Test: Boss Phase Change] │ └────────────────────────────────────────────────┘ ``` ### 反馈效果全局开关(调试用) `FeedbackDebugOverlay`(编辑器 Play Mode 下叠加): - `[Toggle Screen Shake]`:开关镜头震动 - `[Toggle Freeze Frames]`:开关冻帧 - `[Toggle Particles]`:开关粒子特效 - `[Toggle Bullet Time]`:开关子弹时间 方便策划/美术人员单独调试某类反馈。