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