摄像机区域的架构改动

This commit is contained in:
2026-05-15 14:47:24 +08:00
parent 1b37297585
commit f264329751
3591 changed files with 1687228 additions and 446503 deletions

View File

@@ -0,0 +1,424 @@
# 手动测试 06 · 玩家 FSM 与移动系统
> **测试类型**Unity Editor 手动测试Play Mode
> **覆盖模块**`BaseGames.Player`、`BaseGames.Player.States`
> **依赖组件**`PlayerController`、`PlayerMovement`、`AnimancerComponent`、`PlayerStats`
> **场景要求**:包含玩家 Prefab 的测试场景TestRoom.unity地面 Layer = `Ground`
---
## 快速工具
| 工具 | 用途 | 菜单路径 |
|------|------|----------|
| **Place Player** | 在场景中放置带完整组件的玩家 GameObjectPlayerController、PlayerStats、HurtBox 等) | `BaseGames → Scene → Place → Player` |
| **Place Ground Platform** | 放置地面平台BoxCollider2DLayer=Ground | `BaseGames → Scene → Place → Ground Platform` |
| **Place Obstacle (Static)** | 放置静止障碍物(用于蹬墙跳测试墙),手动调整尺寸和位置 | `BaseGames → Scene → Place → Obstacle (Static)` |
| **Place Room Camera** | 放置带 Cinemachine + RoomCamera + CinemachineConfiner2D 的房间相机 | `BaseGames → Scene → Place → Room Camera` |
> **注意**PlayModeDebugOverlay 已移除。Play Mode 运行时调试请使用 `Window → Analysis → EventBus Monitor`(若已集成)或 Console 过滤器查看状态机日志。
**典型工作流**
1. `BaseGames → Scene → Place → Player` 放置玩家;`Place → Ground Platform` 放置地面;`Place → Room Camera` 放置相机。
2. `MT-PLAYER-04` 蹬墙跳测试:`Place → Obstacle (Static)` 在玩家右侧放置垂直墙体,调整位置和尺寸。
3. Play Mode 运行时通过 Inspector 直接修改 HP / Soul 字段,或者利用 Console + EventBus Monitor 观察状态机转换。
---
## 目录
1. [场景搭建要求](#1-场景搭建要求)
2. [MT-PLAYER-01基础移动状态转换](#mt-player-01基础移动状态转换)
3. [MT-PLAYER-02跳跃与下落](#mt-player-02跳跃与下落)
4. [MT-PLAYER-03冲刺地面/空中)](#mt-player-03冲刺地面空中)
5. [MT-PLAYER-04蹬墙滑行与蹬墙跳](#mt-player-04蹬墙滑行与蹬墙跳)
6. [MT-PLAYER-05受击与死亡状态](#mt-player-05受击与死亡状态)
7. [MT-PLAYER-06灵泉治疗](#mt-player-06灵泉治疗)
8. [MT-PLAYER-07形态切换](#mt-player-07形态切换)
9. [MT-PLAYER-08连击链完整性](#mt-player-08连击链完整性)
10. [MT-PLAYER-09存档点复活流程](#mt-player-09存档点复活流程)
---
## 1. 场景搭建要求
在开始任何玩家测试前,确认测试场景包含以下元素:
| 元素 | 说明 | ✓ |
|------|------|---|
| 玩家 Prefab | 挂有 `PlayerController``PlayerMovement``AnimancerComponent``PlayerStats``HurtBox` | ☐ |
| 地面平台 | Layer = `Ground`,带 `Collider2D` | ☐ |
| 墙壁 | 至少一面垂直墙壁Layer = `Ground`,用于蹬墙测试 | ☐ |
| InputReader SO | `PlayerController``_inputReader` 字段已绑定 `InputReaderSO` 资产 | ☐ |
| PlayerStatsSO | `PlayerController``_statsConfig` 字段已绑定 | ☐ |
| PlayerMovementConfigSO | `PlayerMovement``_config` 字段已绑定 | ☐ |
| AnimationConfigSO | `PlayerController``_animConfig` 字段已绑定 | ☐ |
| Physics2D Layer 矩阵 | Player、Ground Layer 碰撞开启 | ☐ |
> **🔧 场景快速搭建**
>
> 1. `BaseGames → Scene → Place → Player` 放置玩家 + `Place → Ground Platform` 生成地面 + `Place → Room Camera` 生成相机
> 2. `MT-PLAYER-04` 蹬墙跳:`Place → Obstacle (Static)` 在玩家右侧放置垂直墙体,调整 Transform 尺寸。
>
> **玩家 Prefab 手动组装(若无预制体)**
>
> 1. 场景 `[Player]` 根节点下创建 `PLY_Player` GameObject
> 2. 添加以下组件:
> - `Rigidbody2D`DynamicFreezeRotationInterpolate
> - `CapsuleCollider2D`尺寸参考美术图层isTrigger=false
> - `AnimancerComponent`(从 Kybernetik.Animancer 包)
> - `PlayerController``BaseGames.Player`
> - `PlayerMovement``BaseGames.Player`
> - `StatusEffectManager``BaseGames.Combat.StatusEffects`
> 3. 创建子 GameObject `HurtBox`isTrigger=trueLayer=PlayerHurtBox并添加 `HurtBox` 组件
> 4. 创建子 GameObject `HitBox_Sword`isTrigger=trueLayer=PlayerHitBox**初始 SetActive(false)**,添加 `HitBox` 组件
> 5. **Inspector 中绑定 SO 字段**
> - `PlayerController._inputReader` → 拖入 `InputReaderSO.asset``Assets/Data/Input/`
> - `PlayerController._statsConfig` → 拖入 `PlayerStats.asset``Assets/Data/Settings/`
> - `PlayerController._animConfig` → 拖入 `AnimationConfig.asset`
> - `PlayerMovement._config` → 拖入 `PlayerMovementConfig.asset`
> 6. 菜单 `BaseGames → Tools → Physics2D Layer Matrix → Check` / **Auto Fix** 确保层碰撞矩阵正确
>
> **一键生成 SO 资产(若尚未创建)**
> 菜单 `BaseGames → Tools → Create Test Assets` 自动生成上述所有 SO 占位资产。
---
## MT-PLAYER-01基础移动状态转换
**目的**:验证 `IdleState → RunState → IdleState` 转换Animancer FSM 动画同步。
### 步骤
1. 进入 Play Mode
2. 玩家站立不动,观察动画
**预期**:播放 `Idle` 动画,无抖动。
3. 按住 **A/D**(或方向键左右)移动
**预期**
- 玩家水平位移,`PlayerMovement.IsGrounded == true`
- 动画切换到 `Run`Animancer 状态可在 Animator 窗口观察)
4. 松开移动键
**预期**
- 玩家减速到静止(`Deceleration` 生效)
- 动画切回 `Idle`
5. 按住移动并朝反方向转向
**预期**
- `SpriteRenderer.flipX` 改变(或 Transform.localScale.x 取反)
- 朝向立即响应,无延迟
| 检查点 | 期望 | ✓ |
|--------|------|---|
| Idle 动画播放 | 无卡帧,无 A-pose | ☐ |
| Run 动画播放 | 移动速度与动画速率匹配 | ☐ |
| 朝向正确 | 面向移动方向 | ☐ |
| Console 无 Error | 0 个红色 Error | ☐ |
---
## MT-PLAYER-02跳跃与下落
**目的**验证跳跃物理弧线、土狼时间Coyote Time、可变跳跃高度提前松键降低高度
### 步骤
**步骤 A普通跳跃**
1. 地面上按 **Space**(跳跃键)
2. 观察轨迹
**预期**:抛物线跳跃弧线,高度约为 `PlayerMovementConfigSO.JumpForce / Gravity`
**步骤 B可变跳跃**
1. 跳跃后立即松开 **Space**
**预期**:玩家跳跃高度降低(`PlayerMovement` 在松键时减少向上速度),动画保持 Jump → Fall 正确过渡。
**步骤 C土狼时间Coyote Time**
1. 让玩家走到平台边缘,**走出平台悬空**
2.`CoyoteTime`(约 0.15s)内按 **Space**
**预期**:跳跃生效(玩家可以从空中起跳),而非立即下落。
**步骤 D下落加速**
1. 跳跃到最高点后松键,等待自然下落
**预期**:下落速度比上升时快(`FallMultiplier` 生效),手感有重量感。
| 检查点 | 期望 | ✓ |
|--------|------|---|
| Jump 动画 | 起跳时播放 Jump 动画 | ☐ |
| Fall 动画 | 下落时切换 Fall 动画 | ☐ |
| 土狼时间有效 | 走出平台后短时内仍可跳跃 | ☐ |
| 落地动画 | 落地瞬间切回 Idle/Run无卡帧 | ☐ |
---
## MT-PLAYER-03冲刺地面/空中)
**目的**:验证 `DashState`(地面)和 `AerialDashState`(空中)的无敌帧、冷却、次数限制。
### 步骤
**步骤 A地面冲刺**
1. 地面上按 **Left Shift**(冲刺键)
**预期**
- 玩家水平快速位移(距离约 `dashDistance`
- 冲刺期间播放 Dash 动画
- 冲刺期间受到敌人攻击**不触发** `HurtState`(无敌帧)
- 冲刺结束后自然过渡 `IdleState``RunState`
**步骤 B空中冲刺**
1. 跳跃后按 **Left Shift**
**预期**
- 空中水平冲刺
- 消耗 `_aerialDashCount`(通常 1 次)
- 落地后次数重置
**步骤 C空中冲刺次数用尽**
1. 空中冲刺 1 次(次数用尽)
2. 再次按冲刺键
**预期**:冲刺不触发(次数为 0 时无反应或有 UI 提示)。
**步骤 D冲刺冷却**
1. 地面冲刺后立即再次按冲刺键
**预期**:冷却期间(`dashCooldown`)无法再次冲刺。
| 检查点 | 期望 | ✓ |
|--------|------|---|
| 地面冲刺位移 | 快速平移 `dashDistance` 距离 | ☐ |
| 无敌帧 | 冲刺期间不受伤 | ☐ |
| 空中冲刺次数 | 次数耗尽后无法再冲 | ☐ |
| 落地重置次数 | 落地后次数恢复 | ☐ |
---
## MT-PLAYER-04蹬墙滑行与蹬墙跳
**目的**:验证 `WallSlideState` 减速下滑、`WallJumpState` 弹离逻辑。
### 步骤
**步骤 A蹬墙滑行**
1. 跳跃接近垂直墙壁,按住朝向墙壁的方向键
2. 玩家贴墙后观察
**预期**
- 下落速度从自由落体减缓到 `wallSlideSpeed`
- 播放 `WallSlide` 动画
**步骤 B蹬墙跳**
1. WallSlide 状态下按 **Space**
**预期**
- 玩家弹离墙壁(方向取反)
- 施加 `wallJumpForce`(包含 X/Y 两个分量)
- 播放 `WallJump` 动画
**步骤 C离墙后方向控制**
1. 蹬墙跳后立即按反向方向键(远离墙壁方向)
**预期**:玩家可控制方向(不被强制锁定朝向太久)。
| 检查点 | 期望 | ✓ |
|--------|------|---|
| WallSlide 减速 | 贴墙后下落速度明显降低 | ☐ |
| WallJump 弹离 | 弹离墙壁,方向翻转 | ☐ |
| 跳跃后可控 | `wallJumpLockTime` 后方向键恢复控制 | ☐ |
---
## MT-PLAYER-05受击与死亡状态
**目的**:验证 `HurtState` 硬直和 `DeadState` 死亡冻结。
### 步骤(需要有能攻击玩家的敌人或调试伤害源)
**步骤 A受击硬直**
1. 让敌人攻击玩家HP 不为 0
2. 观察玩家反应
**预期**
- 受击动画播放
- 硬直期间(`hurtDuration`)玩家无法输入
- 硬直结束后自动恢复 `IdleState`
- HP 减少HUD HP 条更新
**步骤 B死亡**
1. 让玩家 HP 降至 0
**预期**
- 死亡动画播放
- `Rigidbody2D.constraints` 冻结(角色不再受物理影响下移)
- `_onPlayerDied` 事件触发EventBusMonitor 可见)
- 死亡屏幕 UI 出现
| 检查点 | 期望 | ✓ |
|--------|------|---|
| HurtState 动画 | 受击动画播放 `hurtDuration` 秒 | ☐ |
| 硬直期间无法输入 | 按攻击键无反应 | ☐ |
| HP 减少 | HUD HP 条正确减少 | ☐ |
| DeadState 冻结 | 死亡后角色不再移动 | ☐ |
| 死亡 UI | DeathScreen 显示 | ☐ |
---
## MT-PLAYER-06灵泉治疗
**目的**:验证 `SpringState` 治疗动画、灵泉消耗、打断限制。
### 步骤
1. 确保玩家有灵泉(`SpringCount > 0`)且 HP 未满
2.**治疗键**(默认参考 `InputReaderSO` 配置)
**预期**
- 播放治疗动画(`Spring` 动画片段)
- 治疗动画期间不可被打断(敌人攻击触发 `HurtState` 优先级低于 `SpringState` 的硬直保护期)
- 动画结束后 HP 增加(`springHealAmount`
- `SpringCount - 1`HUD 灵泉图标减少
3. 灵泉耗尽后再按治疗键
**预期**:无反应(`SpringCount == 0` 时不进入 `SpringState`)。
| 检查点 | 期望 | ✓ |
|--------|------|---|
| 治疗动画 | Spring 动画播放完整 | ☐ |
| HP 回复 | HP 增加 `springHealAmount` | ☐ |
| 灵泉数量 -1 | HUD 灵泉图标减少 | ☐ |
| 灵泉耗尽 | `SpringCount == 0` 时无法治疗 | ☐ |
---
## MT-PLAYER-07形态切换
**目的**:验证 `FormController` 三形态Sky/Earth/Death切换正确更新外观和事件。
### 步骤
1. 进入 Play Mode
2. 打开 `Window → BaseGames → EventBus Monitor`
3. 按形态切换键(循环切换 Sky → Earth → Death → Sky
**预期(每次切换):**
| 检查点 | 期望 | ✓ |
|--------|------|---|
| 调色板更新 | `SpriteRenderer` 颜色/材质变化Palette Swap | ☐ |
| `EVT_FormChanged` 触发 | EventBusMonitor 显示频道触发 | ☐ |
| `EVT_SkillSetChanged` 触发 | 技能组随形态更新 | ☐ |
| HUD 形态图标 | 形态图标切换到对应形态 | ☐ |
| 武器伤害来源刷新 | 不同形态的武器 SO 绑定正确 | ☐ |
4. 切换到 Earth 形态后存档(与存档点交互)
5. 退出并重新进入 Play Mode加载存档
**预期**:重载后当前形态仍为 Earth`PlayerSaveData.ActiveFormId` 持久化)。
---
## MT-PLAYER-08连击链完整性
**目的**:验证 3 段连击链Attack1 → Attack2 → Attack3、超时重置、空中攻击、下劈/上劈。
### 步骤
**步骤 A3 段地面连击**
1. 地面站立状态,连续快速按 3 次攻击键(间隔在 Combo 窗口内)
**预期**
- 播放 Attack1 → Attack2 → Attack3 三段动画
- 第 3 段结束后返回 Idle不可延续第 4 段
**步骤 B连击超时重置**
1. 按 1 次攻击后等待超时(约 1-2 秒)
2. 再次按攻击键
**预期**:从 Attack1 重新开始Combo 计数重置)。
**步骤 C空中攻击**
1. 跳跃后按攻击键
**预期**:播放 `AirAttack` 动画HitBox 激活(正前方)。
**步骤 D下劈**
1. 跳跃后按 **向下 + 攻击**
**预期**:播放 `DownAttack` 动画;若正下方有敌人,命中后玩家向上反弹(`trampolineForce`)。
**步骤 E上劈**
1. 地面上按 **向上 + 攻击**
**预期**:播放 `UpAttack` 动画HitBox 激活(正上方)。
| 检查点 | 期望 | ✓ |
|--------|------|---|
| 3 段连击 | Attack1→Attack2→Attack3 顺序正确 | ☐ |
| 超时重置 | 超时后从 Attack1 重新开始 | ☐ |
| 空中攻击 | AirAttack 动画,前方 HitBox | ☐ |
| 下劈反弹 | 下方命中后向上弹起 | ☐ |
| 上劈 | UpAttack 动画,上方 HitBox | ☐ |
| 命中灵力增加 | 攻击命中敌人后灵力条增加 | ☐ |
---
## MT-PLAYER-09存档点复活流程
**目的**:端到端验证存档/死亡/复活完整链路。
### 步骤
1. 进入 Play Mode找到场景中的 `SavePoint`(存档点)
2. 走到存档点附近,按交互键(默认 E
3. 确认 Console 出现 `[SaveManager] 存档成功` 日志
4. 让玩家死亡HP 降至 0
5. 在死亡屏幕点击 "重试"(或按确认键)
**预期**
- 玩家复活在存档点位置
- HP 和灵力恢复满值
- 死亡时丢失的 Geo 以 `DeathShade` 形式出现在死亡地点
6. 走到 `DeathShade` 并与其交互
**预期**
- 回收丢失的 Geo
- `DeathShade` 消失
- Geo 数量正确增加
| 检查点 | 期望 | ✓ |
|--------|------|---|
| 存档触发 | SavePoint 交互后存档成功 | ☐ |
| 死亡屏幕 | HP 归零后显示 DeathScreen | ☐ |
| 复活位置 | 复活在存档点,不是死亡地点 | ☐ |
| HP 满值 | 复活后 HP = MaxHP | ☐ |
| DeathShade 出现 | 死亡地点有 DeathShade | ☐ |
| Geo 回收 | 与 DeathShade 交互回收 Geo | ☐ |