chore: initial commit

This commit is contained in:
2026-05-08 11:04:00 +08:00
commit f55d2a57c3
6278 changed files with 866081 additions and 0 deletions

View File

@@ -0,0 +1,351 @@
# 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
/// <summary>
/// 反馈执行器的抽象接口。
/// GameLogic 依赖此接口,而非具体的 MMF_Player 引用。
/// </summary>
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` | Medium0.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.033s2帧| 命中停顿感 |
| `MMF_CinemachineImpulse` | Light0.2强度 | 轻微镜头震 |
### 弹反成功反馈OnParrySuccess
| Feedback | 参数 | 说明 |
|----------|------|------|
| `MMF_Flash` | 金色0.1s | Sprite 金光闪烁 |
| `MMF_Particles` | ParryFlash Prefab全屏金色光圈| 弹反标志性特效 |
| `MMF_AudioSource` | SFX_Parry_Success金属碰撞音| 清脆弹反音效 |
| `MMF_CinemachineImpulse` | Parry0.7强度,带方向 | 有方向性震动 |
| `MMF_TimeScale` | 0.25×0.2s | 子弹时间(与 ParrySystem 同步)|
| `MMF_FreezeFrame` | 0.066s4帧| 更长冻帧强调击中感 |
### 治疗反馈OnHeal
| Feedback | 参数 | 说明 |
|----------|------|------|
| `MMF_Flash` | 蓝色0.2s | 恢复光效 |
| `MMF_Particles` | HealParticle Prefab | 向上飘散的蓝色粒子 |
| `MMF_AudioSource` | SFX_Heal | 回血音效 |
### 死亡反馈OnDeath
| Feedback | 参数 | 说明 |
|----------|------|------|
| `MMF_AudioSource` | SFX_Player_Death | 死亡音效 |
| `MMF_CinemachineImpulse` | Heavy1.0强度 | 强烈震动 |
| `MMF_FreezeFrame` | 0.1s6帧| 死亡冻帧 |
| `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.05s3帧| 击杀冻帧 |
---
## 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`,粒子贴图与角色 PPU32 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]`:开关子弹时间
方便策划/美术人员单独调试某类反馈。