摄像机区域的架构改动

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,350 @@
# 手动测试 09 · 世界与场景系统
> **测试类型**Unity Editor 手动测试Play Mode
> **覆盖模块**`BaseGames.World`、`BaseGames.World.Map`
> **依赖组件**`RoomController`、`RoomTransition`、`SavePoint`、`DeathShade`、`WorldStateRegistry`
> **场景要求**:含多房间连接(至少 2 个 Room SceneAbilityGateMovingPlatformSavePoint
---
## 快速工具
| 工具 | 用途 | 菜单路径 |
|------|------|----------|
| **Place Save Point** | 放置带 SavePoint 组件和 BoxCollider2D(TriggerZone) 的存档点 | `BaseGames → Scene → Place → Save Point` |
| **Place Camera Trigger Zone** | 放置带 CameraTriggerZone 和 BoxCollider2D(TriggerZone) 的摄像机触发区 | `BaseGames → Scene → Place → Camera Trigger Zone` |
| **Place Room Camera** | 放置带 Cinemachine + RoomCamera + CinemachineConfiner2D 的房间摄像机 | `BaseGames → Scene → Place → Room Camera` |
| **Place Ground Platform** | 放置地面平台Layer=Ground | `BaseGames → Scene → Place → Ground Platform` |
| **Place Tilemap Ground** | 放置 Grid + Tilemap + CompositeCollider2DLayer=Ground | `BaseGames → Scene → Place → Tilemap Ground` |
| **Scaffold Room Scene** | 一键生成完整房间场景结构 | `BaseGames → Tools → Scaffold Room Scene` |
> **注意**PlayModeDebugOverlay 已移除。Run Mode 存档调试请直接通过交互键触发存档点,或在 Inspector 中手动调用 `ISaveService.QuickSave()`。
> 房间过渡对象、移动平台、可破坏平台、能力门等复杂对象请参照下方各节的**手动步骤**手工创建。
**典型工作流**
1. `MT-WORLD-01` 房间过渡:手动创建 `RoomTransition` GameObject添加 BoxCollider2D Trigger配置 `_targetSceneAddress`,两端各一个出口(参考下方手动步骤)。
2. `MT-WORLD-02` 存档:`Place → Save Point` 放置存档点Play Mode 交互键激活;确认文件写入通过文件浏览器查看 `Application.persistentDataPath`
3. `MT-WORLD-05` 移动平台 / `MT-WORLD-06` 能力门:手动创建对象,参照各节步骤配置组件(无专用菜单命令)。
---
## 目录
1. [场景结构检查](#1-场景结构检查)
2. [MT-WORLD-01房间过渡RoomTransition](#mt-world-01房间过渡roomtransition)
3. [MT-WORLD-02存档点交互](#mt-world-02存档点交互)
4. [MT-WORLD-03死亡阴影DeathShade](#mt-world-03死亡阴影deathshade)
5. [MT-WORLD-04世界状态持久化WorldStateRegistry](#mt-world-04世界状态持久化worldstateregistry)
6. [MT-WORLD-05可破坏平台与移动平台](#mt-world-05可破坏平台与移动平台)
7. [MT-WORLD-06能力门AbilityGate](#mt-world-06能力门abilitygate)
8. [MT-WORLD-07可收集物Collectibles](#mt-world-07可收集物collectibles)
9. [MT-WORLD-08世界地图显示](#mt-world-08世界地图显示)
---
## 1. 场景结构检查
| 元素 | 说明 | ✓ |
|------|------|---|
| RoomController | 每个 Room Scene 挂有 `RoomController``roomId` 唯一 | ☐ |
| RoomTransition | 房间出入口各有 `RoomTransition``targetSceneName``targetTransitionId` 已配置 | ☐ |
| SavePoint | 测试场景含至少 1 个 `SavePoint`,挂有 `SavePointSO` 资产 | ☐ |
| WorldStateRegistry | 场景挂有 `WorldStateRegistrar` 或 GlobalObject 上有 `WorldStateRegistry` | ☐ |
> **🔧 一键搭建世界测试场景**
>
> | 需求 | 工具 | 操作 |
> |------|------|------|
> | 基础场景(地面 + 玩家) | `BaseGames → Scene → Place → Player` + `Place → Ground Platform` | 分别放置玩家和地面 |
> | 需要存档点MT-WORLD-02 | `BaseGames → Scene → Place → Save Point` | 放置 SavePoint + 手动绑定事件频道 |
> | 需要 2 个 Room 场景MT-WORLD-01 | 手动创建场景(见下方 MT-WORLD-01 步骤) | 注册到 Build Settings + Addressables |
> | 需要死亡阴影MT-WORLD-03 | 手动创建 `DeathShade` GameObject | 挂 `DeathShade` 组件,设置 `_geoAmount = 50` |
> | 需要过渡触发器 | 手动创建 `RoomTransition` GameObject | 挂 BoxCollider2D Trigger + `RoomTransition` 组件 |
>
> **完整世界测试场景搭建顺序**
> 1. `Place → Player` + `Place → Ground Platform`(地面 + 玩家)
> 2. 手动创建 Room_A / Room_B 并注册(仅 MT-WORLD-01 需要)
> 3. `Place → Save Point` + 手动创建 DeathShade
> 4. 手动创建 RoomTransition 对(若在当前单一场景内测试)
> 5. Addressable Batch Tool → 注册 Room_A / Room_B 场景
---
## MT-WORLD-01房间过渡RoomTransition
**目的**:验证 `SceneLoader` + `RoomTransition` 的场景加载/卸载流程Addressables 异步加载)。
> **🔧 资源准备**
>
> 1. 手动创建两个测试场景:`File → New Scene → Empty`,保存为 `Assets/_Game/Scenes/Room_A.unity` 和 `Room_B.unity`,添加地面、`RoomController`、出生点、`RoomTransition` 触发器(左右各一),然后 `File → Build Settings → Add Open Scenes` 注册。
> 2. 用 **Addressable Batch Tool** 将 `Room_A.unity` / `Room_B.unity` 注册Key 建议 = `Room_A` / `Room_B`
> 3. 在两个场景中分别打开对应的 `RoomTransition` GameObject填写 `_targetSceneAddress`
> - `Room_A` 场景的右侧 Transition`_targetSceneAddress = "Room_B"`
> - `Room_B` 场景的左侧 Transition`_targetSceneAddress = "Room_A"`
> 4. 也可在**单一测试场景**中测试(手动创建 RoomTransition 对),但此方案无法测试实际场景卸载/加载
### 步骤
1. 进入 Play Mode
2. 玩家走入场景边缘 `RoomTransition` 触发区域
**预期(过渡动画开始)**
- `ScreenFader` 黑幕淡入(淡出当前场景)
- Console 出现 `[SceneLoader] Loading: RoomB` 类似日志
- `EVT_RoomTransitionStart` 触发EventBusMonitor
**预期(新场景加载完成)**
- 新场景画面淡入
- 玩家出现在目标 `RoomTransition``spawnPoint` 位置
- `EVT_RoomTransitionEnd` 触发
3. 立即再次走回上一个 `RoomTransition`
**预期**可无缝往返无加载错误HP 和状态保持不变。
| 检查点 | 期望 | ✓ |
|--------|------|---|
| 黑幕过渡 | 进出场景时有黑幕淡入淡出 | ☐ |
| 玩家出现位置 | 出现在目标过渡点的 spawnPoint | ☐ |
| 无加载错误 | Console 无 `InvalidKeyException``NullReferenceException` | ☐ |
| 往返正常 | 多次房间切换无内存泄漏或重复 | ☐ |
---
## MT-WORLD-02存档点交互
**目的**:端到端验证 `SavePoint` 激活→存档→读取全流程。
> **🔧 资源准备(一键)**
>
> 使用 `BaseGames → Scene → Place → Save Point` 在场景中快速放置存档点,或手动创建(见下方手动步骤)。
>
> **手动步骤**
> 1. 创建空 GameObject挂 `SavePoint`、`CapsuleCollider2D`isTrigger=true
> 2. 设置 `_savePointId`(唯一字符串,如 `"testroom_SP_01"`
> 3. 将 `EVT_SavePointActivated`StringEventChannelSO拖入 `_onSavePointActivated`
>
> **触发存档**:进入 Play Mode → 走到存档点 → 按 **E 键**(或配置的 Interact 键)激活
> **快速确认**:存档后打开文件浏览器查看 `Application.persistentDataPath` 目录,确认存档文件已生成
### 步骤
1. 走到 `SavePoint`(场景中有 `SavePoint.cs` 的 GameObject
2. 按**交互键**(默认 E 或 F
**预期**
- `SavePoint` 播放激活动画/粒子
- `EVT_SavePointActivated` 触发
- `SaveManager.Save()` 被调用
- Console 出现 `[SaveManager] 存档成功` 日志
- 灵泉次数恢复满值(`SpringCount = MaxSpringCount`
3. 打开存档文件位置验证(`%AppData%\..\LocalLow\[CompanyName]\[AppName]\save.dat`
**预期**:存档文件修改时间与测试时间一致。
4. 退出 Play Mode再进入 Play Mode模拟游戏重启
5. 验证是否从存档点位置开始
**预期**玩家出现在存档点坐标HP 保持存档时的值。
| 检查点 | 期望 | ✓ |
|--------|------|---|
| 激活动画 | SavePoint 激活 VFX/动画播放 | ☐ |
| 存档文件更新 | 存档文件时间戳更新 | ☐ |
| 灵泉恢复 | SpringCount = MaxSpringCount | ☐ |
| 读档位置 | 重启后从存档点出生 | ☐ |
---
## MT-WORLD-03死亡阴影DeathShade
**目的**:验证 `DeathShade` 在死亡位置生成、Geo 附着、回收互动。
> **🔧 资源准备**
>
> **全流程测试(推荐)**
> 1. 确保场景已有存档点(`BaseGames → Scene → Place → Save Point`
> 2. 正常游戏中让玩家死亡 → DeathShade 自动由 `DeathRespawnService` 在死亡位置创建
>
> **快速单元测试(无需真实死亡)**
> - 手动创建 `DeathShade` GameObject挂 `DeathShade` 组件,设置 `_geoAmount = 50`,放置在场景 x=5 位置
> - 进入 Play Mode → 玩家走到 DeathShade 位置 → 观察 Geo 回收交互
> - ⚠ 此为手动占位;完整流程(覆盖测试项 DeathShade 生成位置/第二次死亡覆盖)仍需通过真实死亡触发
### 步骤
1. 确认玩家携带 **Geo > 0**,存档(与存档点交互)
2. 让玩家**在存档点之外的区域死亡**HP 归零)
3. 在死亡屏幕选择重试(复活在存档点)
**预期(复活后)**
- 玩家出现在存档点
- 死亡位置Room B 某坐标)出现 `DeathShade` 对象
- `DeathShade` 持有死亡时的 Geo 数量
4. 走到 `DeathShade` 位置,与其交互(进入触发区域)
**预期**
- Geo 被回收,玩家 `CurrentGeo` 增加
- `DeathShade` 消失(`Destroy``SetActive(false)`
5. 不回收 DeathShade再次死亡
**预期**:旧 `DeathShade` 被新的取代(只保留最新一次),旧 Geo 丢失。
| 检查点 | 期望 | ✓ |
|--------|------|---|
| DeathShade 生成位置 | 出现在死亡坐标 | ☐ |
| Geo 附着 | 显示正确的 Geo 数量 | ☐ |
| 回收 | 交互后 Geo 增加DeathShade 消失 | ☐ |
| 第二次死亡覆盖 | 只保留最新 DeathShade | ☐ |
---
## MT-WORLD-04世界状态持久化WorldStateRegistry
**目的**:验证 `WorldStateRegistry` 中场景状态(门开关、敌人死亡、机关激活)在房间切换后正确持久化。
### 步骤
1. 找到场景中一个可**一次性触发**的机关(如需要击打的开关、某只 One-Shot 敌人)
2. 激活该机关(或击杀该敌人)
3. 记录其 `stateId`Inspector 可查)
4. 离开本房间,进入另一个房间,再返回本房间
**预期**
- 机关仍处于已激活状态(门仍开启)
- One-Shot 敌人不重新生成
- `WorldStateRegistry.GetState(stateId)` 返回 `true`
5. 退出 Play Mode再进入 Play Mode读取存档
**预期**:状态仍持久化(`SaveData.WorldStates` 中有对应 `stateId`)。
| 检查点 | 期望 | ✓ |
|--------|------|---|
| 房间返回后状态 | 机关/敌人状态不重置 | ☐ |
| 读档后状态 | 重新进入 Play Mode 后状态仍持久 | ☐ |
---
## MT-WORLD-05可破坏平台与移动平台
**目的**:验证 `CrumblePlatform`(踩后掉落)和 `MovingPlatform`(循环移动)物理行为。
### CrumblePlatform碎裂平台
1. 站在 `CrumblePlatform`
**预期**
-`crumbleDelay` 秒后平台开始抖动
- 抖动后平台消失Deactivate/Destroy
- 玩家正常下落
2. 等待 `resetTime`
**预期**:平台重新出现(`SetActive(true)` 或重置到初始位置)。
### MovingPlatform移动平台
1. 站在 `MovingPlatform`
**预期**
- 平台在两个 waypoint 之间来回循环移动
- 玩家随平台移动(玩家相对平台位置不变,通过 `transform.SetParent` 或速度叠加实现)
2. 从移动平台跳跃
**预期**:跳跃方向和高度正确(平台速度叠加到跳跃速度)。
| 检查点 | 期望 | ✓ |
|--------|------|---|
| CrumblePlatform 掉落 | 站上后 crumbleDelay 后消失 | ☐ |
| CrumblePlatform 重置 | resetTime 后平台重新出现 | ☐ |
| MovingPlatform 携带玩家 | 站上平台随之移动 | ☐ |
| 平台跳跃 | 速度叠加正确 | ☐ |
---
## MT-WORLD-06能力门AbilityGate
**目的**:验证 `AbilityGate` 根据玩家已解锁能力决定是否通行。
### 步骤
**步骤 A无对应能力时**
1. 确保玩家**未解锁** `AbilityGate` 要求的能力(如 DoubleJump
2. 走到 `AbilityGate`
**预期**:门保持关闭(碰撞体阻挡玩家),显示所需能力提示。
**步骤 B解锁能力后**
1. 通过调试工具或正常流程解锁所需能力
2. 再次走到 `AbilityGate`
**预期**:门开启(碰撞体禁用或动画播放),玩家可通过。
| 检查点 | 期望 | ✓ |
|--------|------|---|
| 无能力 | 门阻挡通行 | ☐ |
| 有能力 | 门开启可通行 | ☐ |
---
## MT-WORLD-07可收集物Collectibles
**目的**验证地图中固定位置收集物Geo 堆、道具)的拾取与持久化。
### 步骤
1. 找到场景中一个 `Collectible` 物品(如固定 Geo 堆)
2. 玩家走过拾取
**预期**
- 拾取动画/音效播放
- 玩家 CurrentGeo 增加
- `Collectible.stateId` 写入 `WorldStateRegistry`
3. 离开房间再返回
**预期**该收集物不再出现One-Shot 语义)。
4. 读取存档重进
**预期**:该收集物仍不出现(状态持久化)。
| 检查点 | 期望 | ✓ |
|--------|------|---|
| 拾取效果 | 动画/音效 + Geo 增加 | ☐ |
| 房间返回 | 不再出现 | ☐ |
| 读档后 | 仍不出现(持久化) | ☐ |
---
## MT-WORLD-08世界地图显示
**目的**:验证 `WorldMap` UI 正确显示已探索房间和玩家当前位置。
### 步骤
1. 在多个房间之间来回切换(探索新房间)
2. 打开世界地图 UI默认 Tab 键)
**预期**
- 已探索的房间在地图上显示(灰色/彩色)
- 未探索的房间不显示(或显示为迷雾)
- 玩家当前位置有图标标识
3. 找到并激活 `MapPin`(地图标记物,如 Boss 房间标记)
**预期**:地图上对应位置出现 `MapPin` 图标(存档后重进仍存在)。
| 检查点 | 期望 | ✓ |
|--------|------|---|
| 已探索房间显示 | 地图正确显示探索过的房间 | ☐ |
| 未探索房间 | 未探索区域显示迷雾或不显示 | ☐ |
| 玩家位置标记 | 玩家图标在正确房间 | ☐ |
| MapPin 持久化 | 存档后 MapPin 仍存在 | ☐ |