33 KiB
手动测试 13 · 玩家能力与技能系统
测试类型:Unity Editor 手动测试(Play Mode)
覆盖模块:BaseGames.Player、BaseGames.Player.States、BaseGames.Skills
依赖组件:PlayerController、PlayerMovement、PlayerStats、PlayerCombat、FormController、SkillManager、SpringSystem、ParrySystem
场景要求:包含玩家 Prefab 的测试场景,至少一块地面平台、一面垂直墙、若干测试用敌人
快速工具
| 工具 | 用途 | 菜单路径 |
|---|---|---|
| Place Player | 放置完整玩家 GameObject | BaseGames → Scene → Place → Player |
| Place Ground Platform | 放置地面平台(Layer=Ground) | BaseGames → Scene → Place → Ground Platform |
| Place Obstacle (Static) | 放置垂直墙壁(用于抓墙测试) | BaseGames → Scene → Place → Obstacle (Static) |
| Place Test Enemy | 放置静止测试用敌人(带 HurtBox) | BaseGames → Scene → Place → Test Enemy |
| Place Room Camera | 放置 Cinemachine 相机 | BaseGames → Scene → Place → Room Camera |
场景搭建要求
在运行所有测试前,请确认以下清单:
| 检查项 | 说明 | ✓ |
|---|---|---|
| 玩家 Prefab 已放置 | 带 PlayerController、PlayerMovement、PlayerStats、PlayerCombat、FormController、SkillManager、SpringSystem、ParrySystem、HurtBox、AnimancerComponent、WeaponManager |
☐ |
| 地面平台 | Layer = Ground,至少一块宽平台 |
☐ |
| 垂直墙壁 | Layer = Ground,高度 ≥ 4 格,用于抓墙/蹬墙跳测试 |
☐ |
| 测试用敌人 | 带 HurtBox、EnemyBase,初始静止,用于攻击/Pogo/灵泉充能测试 |
☐ |
| InputReaderSO | 已绑定 _inputReader 字段 |
☐ |
| PlayerMovementConfigSO | 已绑定,含跳跃/冲刺/墙壁相关参数 | ☐ |
| PlayerAnimationConfigSO | 已绑定,含所有动画 Clip 资产 | ☐ |
| FormConfigSO | 已绑定到 FormController._config,三形态 SO 已配置 |
☐ |
| SkillManager._formSkillSets | Inspector 中已配置三个 FormSkillSet,每项指定对应形态的三个技能 SO |
☐ |
| SkillManager._formController | Inspector 中已绑定 FormController 引用 |
☐ |
| Physics2D Layer 矩阵 | PlayerHitBox ↔ EnemyHurtBox、Player ↔ Ground 碰撞均已开启 | ☐ |
| Console 无红色 Error | 进入 Play Mode 前 Error = 0 | ☐ |
目录
- MT-ABILITY-01:地面三连击与攻击缓冲
- MT-ABILITY-02:上劈(地面 / 空中)
- MT-ABILITY-03:下劈与 Pogo 弹起
- MT-ABILITY-04:空中水平攻击
- MT-ABILITY-05:攻击取消窗口
- MT-ABILITY-06:抓墙与高度记忆机制
- MT-ABILITY-07:蹬墙跳(背墙跳 / 对墙跳)
- MT-ABILITY-08:二段跳
- MT-ABILITY-09:无敌冲刺
- MT-ABILITY-10:三形态切换
- MT-ABILITY-11:三套资源系统
- MT-ABILITY-12:灵泉使用
- MT-ABILITY-13:灵泉充能(击杀积累)
- MT-ABILITY-14:魂技能施放
- MT-ABILITY-15:魄技能施放(技能 1 / 2)
- MT-ABILITY-16:弹反系统
MT-ABILITY-01:地面三连击与攻击缓冲
目的:验证地面三段连击的前摇/有效帧/后摇三阶段、HitBox 激活时序、攻击缓冲机制。
前置条件
- 玩家站于地面
- 在玩家攻击范围内放置测试用敌人
步骤 A:三段连击完整触发
- 进入 Play Mode
- 玩家站立地面,按 Attack 键(默认
J)
预期:
- 播放第 1 段攻击动画(
AnimationConfigSO.GroundAttacks[0]) - 动画前摇结束时 HitBox 激活(可在 Scene 视图 Gizmos 中观察 HitBox 矩形出现)
- 命中敌人后敌人 HP 减少,玩家方向上有微小横向反嵈位移
- 动画进入后摇阶段后(有效帧结束),再次按 Attack 键
预期:
- 无缝衔接第 2 段攻击动画(
GroundAttacks[1]) - 第 2 段 HitBox 重新激活
- 同样方式触发第 3 段
预期:
- 播放
GroundAttacks[2],第三段攻击完成后动画自然结束 - 玩家返回
IdleState或RunState
步骤 B:攻击缓冲(后摇内预输入)
- 按下 Attack 键 触发第 1 段攻击
- 在后摇期间(有效帧结束前后)提前再次按 Attack 键
预期:
- 第 1 段后摇结束后自动衔接第 2 段,无需再次按键
- 缓冲窗口内的输入被
InputBuffer记录并消耗
步骤 C:攻击中断复位
- 第 1 段攻击完成后等待后摇完全结束(约 1.5 秒不操作)
- 再次按 Attack 键
预期:
- 从第 1 段重新开始,而非继续第 2 段(连击计数已重置)
| 检查点 | 期望 | ✓ |
|---|---|---|
| 三段动画各不相同 | 三段 Clip 依次切换 | ☐ |
| HitBox 仅在有效帧激活 | 前摇期间无碰撞,Gizmos 不显示 HitBox | ☐ |
| 命中反嵈 | 命中敌人时玩家微小位移(打击感) | ☐ |
| 攻击缓冲生效 | 后摇内按键可自动续接下一段 | ☐ |
| 连击计数超时重置 | 久未续接后从第 1 段重新开始 | ☐ |
| Console 无 Error | 0 个红色 Error | ☐ |
MT-ABILITY-02:上劈(地面 / 空中)
目的:验证上劈的组合键判定(Move Y 轴正向 + Attack)、向上 HitBox 激活、空中向下反嵈。
前置条件
- 在玩家正上方位置放置测试用敌人(调高 Y 坐标)
步骤 A:地面上劈
- 玩家站立地面
- 按住 Move 上方向键(
W或上方向键,Y 轴正向),同时按 Attack 键
预期:
- 触发上劈动画(
AnimationConfigSO.UpAttack对应 Clip) - HitBox 在角色正上方激活(Scene 视图 Gizmos 可见)
- 命中正上方敌人,敌人 HP 减少
- 玩家仍停留地面,无明显上移(地面上劈无空中反嵈)
步骤 B:空中上劈与向下反嵈
- 跳跃至空中
- 在空中按住 Move 上方向键 + Attack 键
预期:
- 触发上劈动画
- 玩家 Y 轴速度减少约 3(向下反嵈),可在 Inspector →
Rigidbody2D.velocity.y观察到短暂下移 - 上劈动画结束后进入
FallState - 命中敌人后敌人 HP 减少
步骤 C:Move Y 阈值边界
- 空中仅按轻推上方向(Y 轴输入 < 0.5),同时按 Attack 键
预期:
- 触发普通空中水平攻击,而非上劈(Y 阈值未达到 0.5 不判定为上劈)
| 检查点 | 期望 | ✓ |
|---|---|---|
| 地面上劈 HitBox 在上方 | Scene Gizmos 可见上方碰撞盒 | ☐ |
| 空中上劈向下反嵈 | velocity.y 降低约 3,玩家微向下位移 | ☐ |
| Y 轴阈值正确 | 轻推不触发上劈 | ☐ |
| 动画正确 | 播放上劈专属 Clip | ☐ |
MT-ABILITY-03:下劈与 Pogo 弹起
目的:验证下劈仅限空中触发、向下速度施加、命中 Pogo 弹起机制(重置空中能力)、未命中继续下落。
前置条件
- 玩家位于测试敌人正上方(高度 ≥ 3 格)
- 测试敌人带有
HurtBox组件
步骤 A:空中下劈命中 Pogo
- 跳跃至测试敌人正上方
- 按住 Move 下方向键(
S或下方向键,Y 轴负向),同时按 Attack 键
预期:
- 触发下劈动画(
AnimationConfigSO.DownAttack对应 Clip) - 玩家 Y 轴速度被设为约
-18,快速向下冲击 - 下方 HitBox 激活
- 命中敌人后:玩家立即向上弹起(
Pogo Jump,高度固定),与普通跳跃力度相似 - Pogo 触发后空中冲刺次数重置(
_airDashUsed = false) - Pogo 触发后空中跳跃次数重置(
AirJumpsLeft恢复为最大值)
步骤 B:空中下劈未命中
- 在空旷区域(无敌人/无特殊物体)跳跃
- 空中使用下劈
预期:
- 下劈动画和向下速度正常
- 未命中任何目标:玩家不弹起,继续受重力下落至地面
- 落地后进入
IdleState
步骤 C:地面下劈无效
- 玩家站立地面
- 按住 Move 下方向键 + Attack 键
预期:
- 触发普通地面水平攻击(或无响应),不触发下劈
- 下劈判定限制在空中状态
!IsGrounded
步骤 D:Pogo 后续接二段跳
- 解锁二段跳(
PlayerStats.UnlockAbility(AbilityType.DoubleJump),可在 Inspector 勾选) - 空中下劈命中 Pogo 弹起
- 弹起途中按 Jump 键
预期:
- Pogo 重置空中跳跃次数,可再次使用二段跳
| 检查点 | 期望 | ✓ |
|---|---|---|
| 仅限空中触发 | 地面不触发下劈 | ☐ |
| 向下冲击速度 | velocity.y ≈ -18 | ☐ |
| 命中 Pogo 弹起 | 玩家向上弹起,高度固定 | ☐ |
| Pogo 重置冲刺次数 | Pogo 后可再次空中冲刺 | ☐ |
| Pogo 重置跳跃次数 | Pogo 后可再次二段跳(已解锁时) | ☐ |
| 未命中不弹起 | 继续下落至地面 | ☐ |
MT-ABILITY-04:空中水平攻击
目的:验证空中水平攻击(AirAttackState)的触发条件、单次攻击、动画、结束返回 FallState。
步骤 A:空中普通攻击
- 跳跃至空中
- 按 Attack 键(不按方向,或左右方向,Y 轴绝对值 < 0.5)
预期:
- 触发空中水平攻击动画(
AnimationConfigSO.AirAttack) - HitBox 在角色侧面激活(
AttackDirection.Air) - 动画完成后进入
FallState,继续下落 - 命中敌人 HP 减少
步骤 B:空中攻击不循环
- 空中连续多次按 Attack 键
预期:
- 空中攻击为单次,不进行连段
- 每次须等动画结束后重新输入才能再次攻击
| 检查点 | 期望 | ✓ |
|---|---|---|
| 触发空中攻击动画 | 播放 AirAttack Clip | ☐ |
| HitBox 侧面激活 | Scene Gizmos 可见侧面碰撞盒 | ☐ |
| 结束后 FallState | 攻击完成后继续下落,不卡住 | ☐ |
| 单次不循环 | 无法连续多段空中攻击 | ☐ |
MT-ABILITY-05:攻击取消窗口
目的:验证攻击后摇期间的取消窗口允许通过跳跃/冲刺打断攻击动作。
步骤 A:攻击后跳跃取消
- 地面攻击触发第 1 段
- 在有效帧结束后、后摇结束前(取消窗口期间)按 Jump 键
预期:
- 立即从
AttackState转入JumpState - 不必等待后摇完全结束即可起跳
- 取消窗口关闭后(后摇末尾)按 Jump 则无法打断
步骤 B:攻击后冲刺取消
- 地面攻击触发第 1 段
- 在取消窗口期间按 Dash 键
预期:
- 立即进入
DashState,打断后摇
步骤 C:取消窗口外不可取消
- 地面攻击触发第 1 段
- 在前摇期间(有效帧之前)按 Jump 键
预期:
- 跳跃无效,必须等待取消窗口开放后才可取消
| 检查点 | 期望 | ✓ |
|---|---|---|
| 取消窗口内可跳跃 | Jump 立即打断后摇 | ☐ |
| 取消窗口内可冲刺 | Dash 立即打断后摇 | ☐ |
| 前摇内无法取消 | Jump/Dash 在前摇期间无响应 | ☐ |
MT-ABILITY-06:抓墙与高度记忆机制
目的:验证触发条件、无需持续按键维持、高度记忆防无限攀爬逻辑(正常模式静止 / 受限模式下滑)。
前置条件
- 在玩家右侧放置高度 ≥ 6 格的垂直墙壁(Layer=Ground)
步骤 A:基本抓墙触发
- 向右跳跃,在空中接触右侧墙壁
- 按住 Move 右方向键(朝向墙壁方向,X 轴正向)
预期:
- 进入
WallSlideState - 播放抓墙动画
- 松开方向键后角色仍保持抓墙状态(无需持续按键)
步骤 B:主动松墙
- 抓墙状态下按下 Move 左方向键(反方向键)
预期:
- 立即解除抓墙,进入
FallState
步骤 C:正常模式(抓墙高度 ≤ wallGrabY)—— 静止悬挂
- 跳跃至墙壁中部,触发抓墙(记录
wallGrabY) - 松开方向键,观察角色是否移动
预期:
- 角色静止悬挂,Y 坐标不变
- 可以在此状态触发蹬墙跳
步骤 D:受限模式(抓墙高度 > wallGrabY)—— 持续下滑且无法蹬墙跳
- 在 C 的基础上,直接跳跃后更高处再次贴墙(同一面墙,但 Y 坐标高于
wallGrabY) - 触发抓墙,松开方向键
预期:
- 角色持续向下滑动(受限模式)
- 无法触发蹬墙跳(按 Jump 键无效)
💡 操作技巧:从地面站立后直接跳上更高位置并贴墙,此时 Y > wallGrabY(因为上一次落地已重置),也可以先蹬墙跳到更高处再贴同一面墙来制造 Y > wallGrabY 的情况。
步骤 E:落地重置 wallGrabY
- 完成 C 的抓墙后蹬墙跳离墙,落地
- 再次跳跃贴同一面墙(高度与 C 中相同)
预期:
- 落地后
wallGrabY已重置,该高度重新进入正常模式(静止悬挂,可蹬墙跳)
步骤 F:贴另一面墙重置 wallGrabY
- 在步骤 C 中抓右侧墙壁后,蹬墙跳至左侧墙壁
- 在左侧墙壁比之前更高处抓墙
预期:
- 切换到另一面墙壁时
wallGrabY重置为新值 - 该高度为正常模式(可静止,可蹬墙跳)
| 检查点 | 期望 | ✓ |
|---|---|---|
| 朝墙方向键触发抓墙 | 接触墙 + 朝墙输入 → WallSlideState | ☐ |
| 无需持续按键 | 松开方向键后仍保持抓墙 | ☐ |
| 反向键松墙 | FallState | ☐ |
| 正常模式静止 | Y 坐标不变,不下滑 | ☐ |
| 受限模式下滑 | 高于 wallGrabY 时持续下滑 | ☐ |
| 受限模式无蹬墙跳 | Jump 键在受限模式无效 | ☐ |
| 落地重置 | 落地后 wallGrabY 清零 | ☐ |
| 换墙重置 | 抓另一面墙时记录新 wallGrabY | ☐ |
MT-ABILITY-07:蹬墙跳(背墙跳 / 对墙跳)
目的:验证背墙跳(Away)和对墙跳(Toward)的方向判定与施力、视为第一段跳、可变高度支持。
前置条件
- 玩家处于正常抓墙状态(高度 ≤ wallGrabY,可触发蹬墙跳)
步骤 A:背墙跳(Away Jump)
- 抓右侧墙壁,不按任何水平方向键(或按左键,即反方向)
- 按 Jump 键
预期:
- 玩家朝远离右墙方向弹出(向左上方),播放 WallJumpAway 动画
- 弹出后有约 0.2-0.3 秒的水平输入锁定(
_inputLockTimer),锁定结束后可自由控制水平方向 AirJumpsLeft恢复(视为第一段跳)
步骤 B:对墙跳(Toward Jump)
- 抓右侧墙壁,按住 Move 右方向键(朝墙方向)
- 按 Jump 键
预期:
- 玩家朝朝向右墙方向弹出(向右上方),施力偏向竖直,水平分量较小
- 播放 WallJumpToward 动画
- 同样视为第一段跳,
AirJumpsLeft恢复
步骤 C:蹬墙跳后可接二段跳(已解锁时)
- 背墙跳后,在空中再次按 Jump 键
预期:
- 若已解锁二段跳,此时可触发二段跳(
AirJumpsLeft > 0) - 若未解锁,按 Jump 无效
步骤 D:蹬墙跳可变高度
- 背墙跳后立即松开 Jump 键
预期:
- 跳跃高度降低(同普通跳跃可变高度,提前松键截断上升速度)
步骤 E:受限模式下无蹬墙跳
- 使玩家抓墙高度 > wallGrabY(受限模式)
- 按 Jump 键
预期:
- 蹬墙跳不触发(按 Jump 在受限模式无反应)
| 检查点 | 期望 | ✓ |
|---|---|---|
| 背墙跳方向正确 | 远离墙壁斜上方弹出 | ☐ |
| 对墙跳方向正确 | 朝墙壁斜上方弹出,更偏垂直 | ☐ |
| 输入锁定(背墙跳) | 弹出后短时无法控制水平方向 | ☐ |
| 视为第一段跳 | AirJumpsLeft 重置 | ☐ |
| 可接二段跳 | 蹬墙跳后可再次按 Jump(已解锁) | ☐ |
| 可变高度 | 提前松键降低弹跳高度 | ☐ |
| 受限模式无效 | 受限抓墙时 Jump 无响应 | ☐ |
MT-ABILITY-08:二段跳
目的:验证二段跳的解锁门控、空中二次起跳、高度低于一段跳、可变高度支持。
前置条件
- 在
PlayerStatsInspector 中确认AbilityType.DoubleJump是否已解锁 - 步骤 A 使用未解锁状态,步骤 B 及以后需先解锁
步骤 A:未解锁时空中 Jump 无效
- 确认二段跳未解锁(
AbilityFlags中无DoubleJump) - 跳跃至空中
- 在下落途中按 Jump 键
预期:
- Jump 无效,不产生二次跳跃
步骤 B:解锁后空中二段跳
- 在 Inspector 中勾选
DoubleJump解锁(或调用Stats.UnlockAbility(DoubleJump)通过 Console) - 跳跃至空中,在最高点前或下落时按 Jump 键
预期:
- 触发二段跳动画(
DoubleJumpClip) - 玩家再次向上弹起,高度明显低于一段跳
AirJumpsLeft由 1 减为 0
- 二段跳后再次按 Jump 键
预期:
- 无响应(
AirJumpsLeft == 0,无更多空中跳跃机会)
步骤 C:二段跳可变高度
- 二段跳后立即松开 Jump 键
预期:
- 跳跃高度降低(提前松键截断上升速度)
步骤 D:落地重置二段跳次数
- 使用二段跳后落地
- 再次跳跃,在空中按 Jump 键
预期:
AirJumpsLeft已重置(落地时ResetAirJumps()调用),可再次使用二段跳
| 检查点 | 期望 | ✓ |
|---|---|---|
| 未解锁时无效 | 空中 Jump 无响应 | ☐ |
| 解锁后可二段跳 | 空中第二次 Jump 触发 | ☐ |
| 二段跳高度低于一段 | 弹起高度明显更低 | ☐ |
| 二段跳次数限制 | 第三次 Jump 无响应 | ☐ |
| 可变高度 | 提前松键降低高度 | ☐ |
| 落地后重置 | 落地后可再次二段跳 | ☐ |
MT-ABILITY-09:无敌冲刺
目的:验证无敌冲刺的解锁门控、冲刺期间无敌帧(不受伤害)、独立冷却机制。
前置条件
- 在
PlayerStatsInspector 中确认AbilityType.InvincibleDash是否已解锁 - 在测试场景中放置一个会持续攻击的测试敌人(或使用调试工具手动给玩家造成伤害)
步骤 A:未解锁时冲刺无无敌帧
- 确认无敌冲刺未解锁
- 在敌人攻击范围内进行冲刺
预期:
- 冲刺期间受到伤害,进入
HurtState(基础冲刺无无敌帧)
步骤 B:解锁后冲刺无敌帧
- 解锁
InvincibleDash - 在敌人攻击方向上冲刺穿越
预期:
- 冲刺期间不受伤害(
Stats.IsInvincible == true持续DashInvincibilityDuration约 0.20s) - 无敌期间 Inspector 中
IsInvincible字段为 true - 无敌帧结束后恢复正常受伤判定
步骤 C:无敌冲刺独立冷却
- 无敌冲刺后立即再次冲刺
预期:
- 第 2 次冲刺可正常触发(冲刺本身冷却 ≈ 0.4s)
- 但第 2 次冲刺无无敌帧(无敌帧有独立冷却,需等待更长时间恢复)
- Inspector 中
_invincibilityCooldownTimer > 0时不授予无敌
| 检查点 | 期望 | ✓ |
|---|---|---|
| 未解锁无无敌 | 冲刺中受伤进入 HurtState | ☐ |
| 解锁后有无敌帧 | 冲刺期间 IsInvincible=true,不受伤 | ☐ |
| 无敌帧持续时间 | 约 0.20s 后 IsInvincible 变 false | ☐ |
| 独立冷却 | 短时间内第 2 次冲刺无无敌帧 | ☐ |
MT-ABILITY-10:三形态切换
目的:验证三形态切换的输入响应、武器/动画随形态更新、技能集随形态更新。
前置条件
FormConfigSO中三个 FormSO(天魂/地魂/命魂)已配置,各有不同武器 PrefabSkillManager._formSkillSets数组已填写三形态对应的技能 SOWeaponManager已绑定FormController
步骤 A:切换至天魂(SwitchSkyForm)
- 进入 Play Mode,玩家默认形态
- 按 SwitchSkyForm 键(默认
1)
预期:
FormController.CurrentForm.formType == TianHun- 武器切换到天魂武器 Prefab(
WeaponManager.ActiveWeapon更新) SkillManager中_soulSkill、_spirit1、_spirit2替换为天魂对应技能- HUD 形态颜色/图标更新(若已实现 UI 订阅)
- Console 无 Error
步骤 B:切换至地魂(SwitchEarthForm)
- 按 SwitchEarthForm 键(默认
2)
预期:同 A,武器和技能集更换为地魂版本。
步骤 C:切换至命魂(SwitchDeathForm)
- 按 SwitchDeathForm 键(默认
3)
预期:同 A,武器和技能集更换为命魂版本。
步骤 D:切换后攻击使用新武器
- 切换形态后立即攻击
预期:
- HitBox 来自新形态武器实例
- 伤害值使用新形态武器
WeaponSO.Damage
步骤 E:重复切换同一形态
- 当前已在天魂,再次按 SwitchSkyForm 键
预期:
- 无副作用(不重复切换,也不报错)
OnFormChanged事件视实现可能不触发(取决于FormController是否有相同形态判断)
| 检查点 | 期望 | ✓ |
|---|---|---|
| 形态正确更新 | CurrentForm.formType 对应键值 | ☐ |
| 武器随形态切换 | WeaponManager.ActiveWeapon 更新 | ☐ |
| 技能集随形态切换 | SkillManager _soulSkill/_spirit1/_spirit2 更新 | ☐ |
| 攻击使用新武器 | 新武器 HitBox 生效 | ☐ |
| Console 无 Error | 0 个红色 Error | ☐ |
MT-ABILITY-11:三套资源系统
目的:验证灵力、魄元、灵泉次数三者相互独立、各自消耗/恢复逻辑。
步骤 A:灵力(SoulPower)—— 攻击积累
- 在 Inspector 中观察
PlayerStats._currentSoulPower(初始 = 0) - 攻击命中测试敌人多次
预期:
- 每次命中后
_currentSoulPower增加 - 不影响
_currentSpiritPower和_currentSpringCharges
- 消耗至 0(触发魂技能,见 MT-ABILITY-14)
预期:
_currentSoulPower降低_currentSpiritPower不变
步骤 B:魄元(SpiritPower)—— 时间恢复
- 使
_currentSpiritPower低于上限(触发魄技能消耗) - 等待约 3 秒
预期:
_currentSpiritPower每秒自动增加(SpiritRegenRate配置值)- 不影响
_currentSoulPower和_currentSpringCharges
步骤 C:灵泉次数(SpringCharges)—— 三者独立
- 攻击积累灵力,同时魄元自然恢复,灵泉次数保持不变
预期:
- 三个字段完全独立变动,互无影响
| 检查点 | 期望 | ✓ |
|---|---|---|
| 灵力随攻击命中增加 | 每次命中 SoulPower 增加 | ☐ |
| 魄元随时间自动恢复 | 未满时 SpiritPower 逐秒增加 | ☐ |
| 三者独立 | 任一变化不影响其他两项 | ☐ |
MT-ABILITY-12:灵泉使用
目的:验证灵泉使用的前置条件(地面 + 有充能)、HP 恢复、Overlay 动画、充能消耗。
前置条件
PlayerStats._currentSpringCharges > 0(至少 1 次充能)- 玩家 HP 不满(降低 HP 以观察回复效果)
步骤 A:地面使用灵泉
- 玩家站立地面(
IsGrounded == true) - HP 低于上限
- 按 UseSpring 键(默认
E)
预期:
- 播放 Overlay 动画(Layer 1 叠加于 Base Layer 之上),不打断移动动画
_currentSpringCharges减少 1PlayerStats.CurrentHP增加(SpringHealAmount配置值)- 动画结束后玩家返回正常状态
步骤 B:空中使用灵泉无效
- 跳跃至空中(
IsGrounded == false) - 按 UseSpring 键
预期:
- 无响应(
OnUseSpring检测到非地面,直接返回)
步骤 C:充能为 0 时无效
- 确认
_currentSpringCharges == 0 - 地面按 UseSpring 键
预期:
- 无响应(充能为 0 时不进入
SpringState)
步骤 D:Overlay 动画不打断移动
- 地面移动中按 UseSpring 键
预期:
- 使用灵泉 Overlay 动画在 Layer 1 播放
- 玩家可继续移动(Layer 0 移动动画继续)
| 检查点 | 期望 | ✓ |
|---|---|---|
| 地面使用成功 | HP 增加,ChargesCount 减 1 | ☐ |
| 空中无效 | 空中按键无任何响应 | ☐ |
| 充能为 0 无效 | 无充能时按键无响应 | ☐ |
| Overlay 动画叠加 | Layer 1 动画播放,Layer 0 不中断 | ☐ |
MT-ABILITY-13:灵泉充能(击杀积累)
目的:验证 SpringSystem 通过 EVT_EnemyDied 事件积累点数、达到阈值后自动增加灵泉次数。
前置条件
- 场景内有可被击杀的测试敌人
SpringSystem组件挂在玩家或管理器 GameObject 上,_onEnemyDied字段已绑定EVT_EnemyDiedSO 事件资产- 在 Inspector 中调低
PlayerStatsSO.SpringKillThreshold(如设为 2)以方便观察
步骤 A:击杀积累点数
- 攻击并击杀第 1 个测试敌人
预期:
- EVT_EnemyDied 事件触发
PlayerStats._springKillPoints增加 1(可在 Inspector 观察)
- 再次击杀一个敌人
预期:
_springKillPoints增加至阈值- 自动调用
RestoreSpringCharges(1),_currentSpringCharges增加 1 _springKillPoints清零
步骤 B:充能上限限制
- 将
_currentSpringCharges调至上限(MaxSpringCharges) - 继续击杀敌人
预期:
_springKillPoints继续积累- 当
_currentSpringCharges == MaxSpringCharges时,RestoreSpringCharges不超过上限
步骤 C:存档点恢复次数至上限
- 消耗 1 次灵泉
- 与测试场景中的存档点 GameObject 交互(或调用
Stats.RestoreOnSave())
预期:
_currentSpringCharges恢复至MaxSpringCharges_springKillPoints清零(存档点重置积累点)
| 检查点 | 期望 | ✓ |
|---|---|---|
| EVT_EnemyDied 触发点数积累 | 击杀后 _springKillPoints 增加 | ☐ |
| 达阈值自动 +1 次充能 | 积累满后 ChargesCount 增加,点数清零 | ☐ |
| 充能不超上限 | MaxSpringCharges 限制 | ☐ |
| 存档点恢复至上限 | ChargesCount = MaxSpringCharges | ☐ |
MT-ABILITY-14:魂技能施放
目的:验证 SkillManager 响应 SoulSkill 输入、消耗灵力、播放技能动画、冷却限制。
前置条件
- 当前形态已配置
FormSkillSet.soulSkill(有效的FormSkillSO资产) PlayerStats._currentSoulPower达到技能消耗量以上
步骤 A:灵力充足时施放魂技能
- 攻击敌人积累足够灵力(
_currentSoulPower ≥ soulSkill.Cost) - 按 SoulSkill 键(默认
Q)
预期:
- 技能动画播放(
FormSkillSO.animationClip) _currentSoulPower减少soulSkill.Cost- 技能特效实例化(若
FormSkillSO中配置了 VFX) - 技能进入冷却(
_cooldowns[soulSkill]开始计时)
步骤 B:冷却中无法再次施放
- 技能施放后立即再次按 SoulSkill 键
预期:
- 无响应(冷却剩余
> 0时拒绝施放)
步骤 C:灵力不足时无法施放
_currentSoulPower < soulSkill.Cost(可通过消耗后立即尝试)- 按 SoulSkill 键
预期:
- 无响应(灵力不足,
SkillManager内部判断拒绝)
步骤 D:形态切换后技能变更
- 切换到另一个形态
- 按 SoulSkill 键
预期:
- 施放的是新形态的魂技能(不同动画、不同效果)
| 检查点 | 期望 | ✓ |
|---|---|---|
| 灵力充足时施放成功 | 动画播放,SoulPower 减少 | ☐ |
| 冷却中无法施放 | 再次按键无响应 | ☐ |
| 灵力不足无法施放 | 资源不足时无响应 | ☐ |
| 形态切换后使用新技能 | 切换形态后施放新形态魂技能 | ☐ |
MT-ABILITY-15:魄技能施放(技能 1 / 2)
目的:验证 SpiritSkill1/SpiritSkill2 的消耗魄元、独立冷却、形态切换更新。
前置条件
- 当前形态已配置
FormSkillSet.spiritSkill1和spiritSkill2 PlayerStats._currentSpiritPower充足
步骤 A:施放魄技能 1
- 按 SpiritSkill1 键(默认
R,长按触发 Start,松开触发 Cancelled)
预期:
- 技能动画播放
_currentSpiritPower减少spiritSkill1.Cost- 若技能为蓄力型,按住触发蓄力动画,松开触发释放
步骤 B:施放魄技能 2
- 按 SpiritSkill2 键(默认
F)
预期:
- 施放魄技能 2(不同动画/效果)
- 消耗独立的魄元量(
spiritSkill2.Cost)
步骤 C:技能 1 和技能 2 冷却独立
- 依次施放技能 1 和技能 2
预期:
- 技能 1 冷却中不影响技能 2 的施放(
_cooldowns字典各自独立计时)
步骤 D:魄元自动恢复后可再次施放
- 魄技能消耗魄元后等待恢复
- 再次施放
预期:
- 魄元恢复至足够后可再次施放(
SpiritRegenRate自动回复)
| 检查点 | 期望 | ✓ |
|---|---|---|
| 技能 1 施放成功 | 动画播放,SpiritPower 减少 | ☐ |
| 技能 2 施放成功 | 不同动画,SpiritPower 减少 | ☐ |
| 冷却独立 | 技能 1 冷却不阻止技能 2 | ☐ |
| 形态切换后使用新技能 | 新形态的魄技能 1/2 生效 | ☐ |
| 魄元恢复后可再施放 | 等待后 SpiritPower 恢复,可用 | ☐ |
MT-ABILITY-16:弹反系统
目的:验证 ParrySystem/ParryState 的触发窗口、弹反成功判定、灵力奖励、护盾恢复。
前置条件
- 场景中有能发动近战攻击的测试敌人(或使用 Debug 工具手动触发弹反机会)
ParrySystem已绑定InputReaderSOShieldComponent已配置(若需验证护盾恢复)
步骤 A:弹反触发与成功
- 敌人发起攻击时,在攻击即将命中前按下弹反键(
Parry,默认K)
预期:
- 进入
ParryState,播放弹反动画 - 若在弹反窗口内成功拦截敌人攻击:
- 弹反命中判定成功,敌人受到弹反反馈(硬直或被弹飞)
PlayerStats._currentSoulPower增加(ParryInfo.SoulGained)ShieldComponent.OnParrySuccess()调用(护盾恢复)- 玩家不受任何伤害(弹反期间有效)
步骤 B:弹反窗口外受伤
- 弹反动画开始后等待窗口结束(约 0.2-0.3s 后),此时再受到敌人攻击
预期:
- 玩家正常受伤,进入
HurtState(弹反窗口已关闭)
步骤 C:空弹反(无敌人攻击)
- 地面不受攻击时按弹反键
预期:
- 播放弹反动画
- 弹反窗口结束后自动返回
IdleState - 无报错,无副作用
| 检查点 | 期望 | ✓ |
|---|---|---|
| 弹反动画播放 | ParryState 正确进入 | ☐ |
| 弹反成功不受伤 | 窗口内拦截,玩家 HP 不减少 | ☐ |
| 灵力奖励 | SoulPower 增加 SoulGained 值 | ☐ |
| 护盾恢复 | ShieldComponent.OnParrySuccess 调用 | ☐ |
| 窗口外受伤 | 窗口关闭后受攻击进入 HurtState | ☐ |
| 空弹反无副作用 | 无敌人攻击时弹反后正常返回 Idle | ☐ |
附录 A:Inspector 调试辅助字段
以下字段在 Play Mode 下可在 Inspector 中实时观察,便于调试:
| GameObject | 组件 | 字段 | 含义 |
|---|---|---|---|
| Player | PlayerController |
_dbg_CurrentState |
当前 FSM 状态名 |
| Player | PlayerController |
_dbg_IsGrounded |
是否落地 |
| Player | PlayerController |
_dbg_AirJumpsLeft |
剩余空中跳跃次数 |
| Player | PlayerController |
_dbg_CanDash |
当前是否可冲刺 |
| Player | PlayerController |
_dbg_IsInvincible |
当前是否无敌 |
| Player | PlayerStats |
_currentHP |
当前 HP |
| Player | PlayerStats |
_currentSoulPower |
当前灵力 |
| Player | PlayerStats |
_currentSpiritPower |
当前魄元 |
| Player | PlayerStats |
_currentSpringCharges |
当前灵泉次数 |
| Player | PlayerStats |
_springKillPoints |
当前灵泉积累点 |
| Player | FormController |
CurrentForm |
当前形态 SO |
| Player | SkillManager |
_soulSkill |
当前魂技能 |
| Player | SkillManager |
_spirit1 |
当前魄技能 1 |
| Player | SkillManager |
_spirit2 |
当前魄技能 2 |
附录 B:常见问题排查
| 问题现象 | 可能原因 | 排查步骤 |
|---|---|---|
| 攻击无 HitBox 效果 | WeaponManager 武器未实例化 | Inspector 检查 WeaponManager.ActiveHitBoxInstance 是否为 null |
| 形态切换后技能未更新 | SkillManager._formController 未赋值 |
确认 Inspector 中已拖入 FormController 引用,并检查 _formSkillSets 数组长度 ≥ 3 |
| 灵泉使用无响应 | UseSpringEvent 未绑定 |
检查 InputReaderSO 中 UseSpring Action 名称拼写,确认 PlayerController 已订阅 |
| 抓墙后立即滑落 | WallDetector 未检测到墙 | 检查墙壁 Layer 是否为 Ground,PlayerWallDetector 的 wallLayer 掩码包含该 Layer |
| 蹬墙跳无效 | 受限模式(高于 wallGrabY) | 在受限模式(下滑状态)时蹬墙跳设计上不可用,属预期行为 |
| 魄技能冷却独立验证失败 | 技能 SO 资产共用同一实例 | 确认技能 1、技能 2 使用的是不同 FormSkillSO 资产(不同 .asset 文件) |
| Pogo 未弹起 | DownAttackState OnDownHitConfirmed 未订阅 |
检查 PlayerCombat._currentHitBoxInstance 是否正确订阅,Console 查看 HandleWeaponChanged 是否调用 |
| Console 出现 NullReferenceException | Inspector 中某 SO/组件字段未赋值 | 运行时在 PlayerController.Awake 的 Debug.Assert 输出中查看具体缺失字段 |