Files
Cielonos/docs/闪避反馈系统实现进度.md
2026-04-18 13:57:19 -04:00

11 KiB
Raw Permalink Blame History

Cielonos 闪避反馈系统实现进度

已完成的工作

1. 代码架构修改

1.1 DodgeSource.Default() 方法重构

  • 文件Assets/Scripts/MainGame/Characters/Base/Subcontrollers/Reaction/DodgeSubmodule.cs
  • 修改移除了MMF_Feedback相关的代码MMF_RadialBlur、MMF_AdvancedVignette
  • 状态 完成

1.2 PlayerAnimationSubcontroller 闪避反馈重构

  • 文件Assets/Scripts/MainGame/Characters/Player/Animation/PlayerAnimScDashDodge.cs
  • 修改
    • 移除了所有MMF_Feedback引用
    • Dash反馈使用新的player.feedbackSc.PlayFeedback("Dash")
    • Dodge反馈使用新的player.feedbackSc.PlayFeedback("Dodge")
  • 状态 完成

1.3 EventSubmodule 新增事件

  • 文件Assets/Scripts/MainGame/Characters/Base/Submodules/EventSubmodule.cs
  • 新增事件
    • onDodgeSuccess - 完美闪避成功时触发
    • onNormalDodgeSuccess - 普通闪避成功时触发
  • 状态 完成

1.4 Player 事件监听注册

  • 文件Assets/Scripts/MainGame/Characters/Player/Player.cs
  • 新增内容
    • InitializeSubmodules()中注册PerfectDodge和NormalDodge事件监听
    • 新增Feedback_PerfectDodge()方法:播放完美闪避反馈
    • 新增Feedback_NormalDodge()方法:处理普通闪避反馈
  • 状态 完成

1.5 ReactionSubmodule 事件触发

  • 文件Assets/Scripts/MainGame/AttackArea/Submodules/ReactionSubmodule.cs
  • 修改
    • 完美闪避成功后触发dodger.eventSm.onDodgeSuccess.Invoke(firstDodgeSource)
    • 普通闪避成功后触发dodger.eventSm.onNormalDodgeSuccess.Invoke(firstDodgeSource)
  • 状态 完成

📋 FeedbackData 配置状态

已创建的FeedbackData文件

位置:Assets/Prefabs/MainGame/Characters/Player/Data/Feedbacks/

文件名 用途 配置状态
Player_Feedback_Dash.asset 冲刺反馈 ⚠️ 待配置
Player_Feedback_Dodge.asset 后撤步反馈 ⚠️ 待配置
Player_Feedback_NormalDodge.asset 普通闪避反馈 ⚠️ 待配置
Player_Feedback_PerfectDodge.asset 完美闪避反馈 ⚠️ 待配置

注意这些文件已创建但tracks为空需要在Unity编辑器中配置。


🎯 FeedbackData 配置指南

2.1 Dash冲刺FeedbackData 配置

目标:强调速度感、移动感

Track 1: "Camera" - 相机效果

Clip 1: CameraFieldOfViewAction
  - FOV增量: +6°
  - 持续时间: 0.2秒
  - 曲线: FadeOut

Track 2: "Camera" - 旋转震动

Clip 1: CameraRotationShakeAction
  - Rotation: (1°, 0.5°, 2°)
  - 持续时间: 0.15秒
  - 曲线: QuickImpact

Track 3: "PostProcess" - 径向模糊

Clip 1: RadialBlurAction
  - Intensity: 0.25
  - 持续时间: 0.15秒
  - 曲线: FadeOut

2.2 Dodge后撤步FeedbackData 配置

目标:强调突然性、灵活性

Track 1: "Camera" - 相机效果

Clip 1: CameraFieldOfViewAction
  - FOV增量: +5°
  - 持续时间: 0.2秒
  - 曲线: FadeOut

Track 2: "Camera" - 旋转震动

Clip 1: CameraRotationShakeAction
  - Rotation: (0.5°, 0.3°, 1.5°)
  - 持续时间: 0.12秒
  - 曲线: QuickImpact

Track 3: "PostProcess" - 径向模糊

Clip 1: RadialBlurAction
  - Intensity: 0.2
  - 持续时间: 0.12秒
  - 曲线: FadeOut

2.3 NormalDodge普通闪避FeedbackData 配置

说明NormalDodge用于普通闪避非冲刺的短距离闪避

Track 1: "Camera" - 相机效果

Clip 1: CameraFieldOfViewAction
  - FOV增量: +4°
  - 持续时间: 0.15秒
  - 曲线: FadeOut

Track 2: "Camera" - 旋转震动

Clip 1: CameraRotationShakeAction
  - Rotation: (0.3°, 0.2°, 1°)
  - 持续时间: 0.1秒
  - 曲线: QuickImpact

Track 3: "PostProcess" - 径向模糊

Clip 1: RadialBlurAction
  - Intensity: 0.15
  - 持续时间: 0.1秒
  - 曲线: FadeOut

2.4 PerfectDodge完美闪避FeedbackData 配置

目标:时间扭曲 + 视觉强化 + 成就感

Track 1: "Time" - 时间缩放

Clip 1: TimeScaleModifierAction
  - Mode: Dynamic
  - Curve: Custom
  - RemapZero: 0.3
  - RemapOne: 1.0
  - 持续时间: 0.3秒
  - ⚠️ 重要此Track不应受全局时间缩放影响

Track 2: "Camera" - FOV变化

Clip 1: CameraFieldOfViewAction
  - FOV增量: +10°
  - 持续时间: 0.35秒
  - 曲线: FadeOut

Track 3: "Camera" - 旋转震动

Clip 1: CameraRotationShakeAction
  - Rotation: (3°, 2°, 5°)
  - 持续时间: 0.3秒
  - 曲线: QuickImpact

Track 4: "PostProcess" - 暗角

Clip 1: VignetteAction
  - Intensity: 0.4
  - 持续时间: 0.35秒
  - 曲线: FadeOut

Track 5: "PostProcess" - 径向模糊

Clip 1: RadialBlurAction
  - Intensity: 0.6
  - 持续时间: 0.25秒
  - 曲线: FadeOut

Track 6: "PostProcess" - 色差

Clip 1: ChromaticAberrationAction
  - Intensity: 0.25
  - 持续时间: 0.2秒
  - 曲线: FadeOut

🔧 接下来的步骤

步骤1在Unity编辑器中配置FeedbackData

  1. 打开Unity编辑器
  2. 导航到 Assets/Prefabs/MainGame/Characters/Player/Data/Feedbacks/
  3. 逐个配置上述FeedbackData文件

步骤2在Player Prefab中关联FeedbackData

  1. 选择Player Prefab
  2. 找到FeedbackDataCollection组件
  3. 确保以下键值对存在:
    • "Dash" → Player_Feedback_Dash.asset
    • "Dodge" → Player_Feedback_Dodge.asset
    • "NormalDodge" → Player_Feedback_NormalDodge.asset
    • "PerfectDodge" → Player_Feedback_PerfectDodge.asset

步骤3测试

  1. 进入游戏
  2. 测试冲刺反馈
  3. 测试后撤步反馈
  4. 测试普通闪避反馈
  5. 测试完美闪避反馈(需要被敌人攻击时在完美时机闪避)

步骤4根据体验调整参数

根据实际手感调整:

  • FOV变化量
  • 震动强度
  • 模糊程度
  • 时间缩放值

📊 代码流程图

玩家触发闪避
    ↓
PlayerAnimationSubcontroller.SetupDash/SetupDodge()
    ↓
PlayerAnimationSubcontroller.DashStart/DodgeStart()
    ↓
player.feedbackSc.PlayFeedback("Dash"/"Dodge")  // 播放普通闪避反馈
    ↓
ApplyDodge() → 添加闪避源
    ↓
敌人攻击命中
    ↓
ReactionSubmodule.CheckDodge()
    ↓
判断是否完美闪避
    ↓
DodgeSource.PerfectDodge() / NormalDodge()
    ↓
触发事件: dodger.eventSm.onDodgeSuccess/onNormalDodgeSuccess
    ↓
Player.Feedback_PerfectDodge() / Feedback_NormalDodge()
    ↓
player.feedbackSc.PlayFeedback("PerfectDodge")  // 播放完美闪避反馈

⚠️ 注意事项

  1. 时间缩放PerfectDodge的TimeScaleModifierAction必须不受全局时间缩放影响
  2. 性能同时激活的效果不要超过5个
  3. 调试可以在Player.Feedback_PerfectDodge()中添加Debug.Log用于调试

🔧 问题修复TimeScaleModifierAction立即生效

问题描述

当PerfectDodge播放时TimeScaleModifierAction修改的globalTimeScale在同一帧内不会立即被其他Feedback读取到。

原因

  • TimeScaleModifierAction.OnStart()调用TimeScaleShakeEvent.Trigger()
  • 只是注册了TimeScaleShakeInstance
  • TimeScaleShaker.Update()在下一帧才执行
  • 其他Feedback的ComputeClipDeltaTime()已经读取了旧的globalTimeScale值

解决方案

在TimeScaleModifierAction.OnStart()中立即应用一次时间缩放调用ImmediateApplyTimeScale()

修改内容

  • 文件TimeScaleModifierAction.cs
  • 添加ImmediateApplyTimeScale()方法
  • 在OnStart()末尾调用ImmediateApplyTimeScale()

代码

public override void OnStart(FeedbackContext context)
{
    // 原有逻辑...
    TimeScaleShakeEvent.Trigger(...);
    
    // 新增:立即应用时间缩放
    ImmediateApplyTimeScale();
}

private void ImmediateApplyTimeScale()
{
    if (TimeManager.Instance == null) return;
    
    float t = 0f;  // 归一化时间0
    
    if (globalChannel.active)
        TimeManager.Instance.globalTimeScale.Value = globalChannel.Evaluate(t);
    
    if (playerChannel.active)
        TimeManager.Instance.playerTimeScale.Value = playerChannel.Evaluate(t);
    
    if (enemyChannel.active)
        TimeManager.Instance.enemyTimeScale.Value = enemyChannel.Evaluate(t);
    
    if (alliedChannel.active)
        TimeManager.Instance.alliedMinionTimeScale.Value = alliedChannel.Evaluate(t);
    
    if (nonPlayerChannel.active)
        TimeManager.Instance.nonPlayerTimeScale.Value = nonPlayerChannel.Evaluate(t);
}

效果

现在当PerfectDodge播放时

  1. TimeScaleModifierAction立即修改globalTimeScale = 0.1
  2. 同一帧内其他Feedback能立即读取到0.1
  3. 所有效果在同一帧内协调生效

🔧 关键修复ProcessClip的pending分支elapsed计算

问题描述

当CameraFOV等Feedback在PerfectDodge播放期间持续处于pending状态时等待estimatedEndTime满足它们的elapsed时间会累积。

当终于进入active状态时使用了elapsed = _currentTime - startTime计算导致elapsed很大可能是10秒然后在active分支中elapsed >= safeDuration立即为trueClip立即结束。

时间线示例

PerfectDodge播放第1帧:  _currentTime = 0.016, CameraFOV.pending (estimatedEndTime=10.032)
PerfectDodge播放第100帧: _currentTime = 1.6,    CameraFOV.pending (estimatedEndTime=11.616)
PerfectDodge播放结束时:   CameraFOV终于满足estimatedEndTime >= _currentTime
                        elapsed = _currentTime - 0 = 1.6 (或更大)
                        elapsed >= safeDuration(0.2) 立即为true
                        CameraFOV.OnEnd()立即被触发!

解决方案

在pending->active分支中elapsed = _currentTime - startTime改为elapsed = 0f

修改内容

  • 文件FeedbackPlayer.cs
  • 位置ProcessClip方法的pending分支
  • 修改:将elapsed = _currentTime - clip.startTime改为elapsed = 0f

代码

case ClipState.Pending:
    if (_currentTime >= clip.startTime)
    {
        clipState = ClipState.Active;
        // 关键修复当Clip进入active状态时elapsed应该从0开始
        elapsed = 0f;
        // ...
    }
    break;

效果

  • Clip进入active状态时elapsed从0开始
  • 不会被之前累积的_currentTime影响
  • Clip的持续时间正确

📝 待办事项清单

  • 在Unity编辑器中配置Player_Feedback_Dash.asset
  • 在Unity编辑器中配置Player_Feedback_Dodge.asset
  • 在Unity编辑器中配置Player_Feedback_NormalDodge.asset
  • 在Unity编辑器中配置Player_Feedback_PerfectDodge.asset
  • 在Player Prefab中关联所有FeedbackData
  • 测试Dash反馈
  • 测试Dodge反馈
  • 测试NormalDodge反馈
  • 测试PerfectDodge反馈
  • 根据手感调整参数

文档生成日期: 2026-04-17
生成者: Game Designer Agent
状态: 代码已完成,待编辑器配置