Files
zeling_v2/Docs/Verification/12_Manual_CameraSystem.md

21 KiB
Raw Blame History

手动测试 12 · 区域相机系统

测试类型Unity Editor 手动测试Play Mode
覆盖模块CameraAreaCameraTriggerZoneCameraStateControllerCinemachineConfiner2DCameraBlendProfileSO
前置文档Phase1_Verification_Guide.md §1验证前准备


快速工具

工具 用途 菜单路径
Camera Area Setup窗口 扫描场景中所有 CameraArea/TriggerZone/Controller显示绑定状态提供一键修复 BaseGames → Camera → Camera Area Setup
Place Camera Area 生成 CameraArea 节点(含 PolygonCollider2D 限位边界) BaseGames → Scene → Place → Camera Area
Place Camera Trigger Zone 生成 CameraTriggerZone + BoxCollider2D Trigger BaseGames → Scene → Place → Camera Trigger Zone

典型工作流

  1. 在 Persistent 场景中放置两台全局虚拟相机(VCamA / VCamB),绑定到 CameraStateController._vcamA/_vcamB
  2. 在关卡场景中使用 Place Camera Area 为每个相机区域放置 CameraArea 数据节点(一个房间可放多个)。
  3. 选中 CameraArea,在 Scene 视图中拖拽黄色可视区域的边 Handle 调整可见范围,然后点击 Inspector 底部 「从可视区域更新限位区域(透视)」 自动换算限位多边形。
  4. 使用 Place Camera Trigger Zone 在区域入口放置触发器,并将目标 CameraArea 拖入 _targetArea
  5. 打开 Camera Area Setup 窗口,点击 为全局 VCam 赋值 Follow 目标(会自动在 Player 下创建或复用 CameraFollowTarget 子节点并绑定)。
  6. 所有条目显示绿色 ● → 进入 Play Mode 验证。

目录

  1. 系统架构说明
  2. Persistent 场景配置CameraStateController
  3. 关卡场景配置CameraArea + CameraTriggerZone
  4. ScriptableObject 资产说明
  5. Camera Area Setup 工具详解
  6. 验收测试用例
  7. 常见问题排查

1. 系统架构说明

Persistent.unity
└── [Camera]
    └── CameraStateController          ExecutionOrder = -100
          组件: CameraStateController
          │     _vcamA → VCamA全局虚拟相机 A
          │     _vcamB → VCamB全局虚拟相机 B
          组件: CinemachineBrain        ← 实际渲染相机(随 Main Camera 放置)
          组件: CinemachineImpulseSource ← 屏幕抖动信号源
    ├── VCamA
    │     组件: CinemachineCamera       Follow = Player/CameraFollowTarget
    │     组件: CinemachineConfiner2D   ← 由 CameraStateController 动态更新 BoundingShape2D
    └── VCamB
          组件: CinemachineCamera       Follow = Player/CameraFollowTarget
          组件: CinemachineConfiner2D   ← 由 CameraStateController 动态更新 BoundingShape2D

Level_01.unity
├── [CameraAreas]
│   ├── CameraArea_A                   区域 A可在同一房间内放置多个
│   │   组件: CameraArea               _confinerCollider → PolygonCollider2D
│   │   │                             _visibleBounds可视矩形
│   │   │                             _blendProfile → CameraBlendProfileSO可选
│   │   │                             _dedicatedCamera专有 VCam可选priority > 全局)
│   │   └── PolygonCollider2D         定义该区域的相机限位边界
│   │
│   └── CameraArea_B                   区域 B
│       ...(同上)
│
└── [Triggers]
    ├── CameraTriggerZone_AB           区域 A→B 入口
    │   组件: CameraTriggerZone         _targetArea = CameraArea_B
    │   组件: BoxCollider2D             isTrigger = true
    └── CameraTriggerZone_BA           区域 B→A 入口
        组件: CameraTriggerZone         _targetArea = CameraArea_A
        组件: BoxCollider2D             isTrigger = true

核心流程

  1. 玩家进入 CameraTriggerZoneOnTriggerEnter2D 调用 ICameraService.SwitchArea(targetArea)
  2. CameraStateController.SwitchArea → 应用 BlendProfileCinemachineBrain.DefaultBlend
    • 无专有 VCam:配置非活跃全局 VCam 的 CinemachineConfiner2D.BoundingShape2D → 提升其优先级至 10 → 降低旧 VCam 优先级至 0ping-pongCinemachine Brain 自动触发混合过渡
    • 有专有 VCam:提升 _dedicatedCamera 优先级至 _dedicatedPriority(默认 20高于全局 VCamCinemachine 自动切换

2. Persistent 场景配置CameraStateController

2.1 组件放置

在 Persistent 场景的 [Camera] 下建立以下节点结构:

GameObject 挂载组件 说明
[CameraController] CameraStateControllerCinemachineBrainCinemachineImpulseSource ExecutionOrder = -100
VCamA CinemachineCameraCinemachineConfiner2D 全局虚拟相机 A拖入 CameraStateController._vcamA
VCamB CinemachineCameraCinemachineConfiner2D 全局虚拟相机 B拖入 CameraStateController._vcamB

注意CinemachineBrain 须挂在附有 Camera 组件Main Camera的 GameObject 上, 否则 Cinemachine 无法驱动视口渲染。两台全局 VCam 初始优先级均为 0CameraStateController 在运行时动态管理。

2.2 字段绑定清单

打开 Camera Area Setup 窗口(BaseGames → Camera → Camera Area SetupCameraStateController 区域确认以下项目全为绿色 ●:

字段 期望状态
_vcamA (CinemachineCamera) ● 已绑定
_vcamB (CinemachineCamera) ● 已绑定
_brain (CinemachineBrain) ● 已绑定
_impulseSource (CinemachineImpulseSource) ◌ 可选;用于屏幕抖动
_defaultBlendProfile (CameraBlendProfileSO) ◌ 可选;未设置则无混合过渡

3. 关卡场景配置CameraArea + CameraTriggerZone

3.1 添加 CameraArea

方式 A使用快速放置工具(推荐)

  1. 菜单 BaseGames → Scene → Place → Camera Area
  2. 工具自动创建以下节点结构:
    CameraArea
    ├── CameraArea组件_confinerCollider 已绑定)
    └── PolygonCollider2D默认矩形 24×12isTrigger = true定义限位区域
    
  3. 打开 Camera Area Setup 窗口,点击 为全局 VCam 赋值 Follow 目标 (工具会自动在 Player 下查找或创建 CameraFollowTarget 子节点,绑定到两台全局 VCam
  4. 手动调整子节点 PolygonCollider2D 顶点定义限位范围。

方式 B手动创建

  1. 新建空 GameObject命名如 CameraArea_A
  2. 挂载 CameraAreaBaseGames.Camera
  3. 在同一 GameObject 或子对象上创建 PolygonCollider2D
  4. PolygonCollider2D 拖入 CameraArea._confinerCollider
  5. (可选)如需专有相机参数,新建独立 VCam GameObject挂载 CinemachineCamera,拖入 CameraArea._dedicatedCamera

一个房间可放置多个 CameraArea,如大厅区域与 Boss 区域分别使用不同的限位和混合配置。

3.2 调整限位区域PolygonCollider2D

CameraArea 上(或子节点)的 PolygonCollider2D 定义了相机在该区域内的移动边界。

  • 编辑顶点:选中 CameraArea 节点 → Inspector 中 PolygonCollider2D → 点击 Edit Collider 图标,在 Scene 视图拖动顶点
  • 自动修复:打开 Camera Area Setup 窗口,对应条目点击 修复:绑定子节点 PolygonCollider2D

最佳实践:限位区域应比实际可见范围大一格以上(约 1 unit避免相机卡在边缘。

3.3 添加 CameraTriggerZone

使用快速放置工具(推荐)

  1. 菜单 BaseGames → Scene → Place → Camera Trigger Zone
  2. 工具生成:
    CameraTriggerZone
    ├── CameraTriggerZone组件_playerTag = "Player"
    └── BoxCollider2DisTrigger = true默认 2×2
    
  3. 在 Inspector 中将目标 CameraArea 拖入 CameraTriggerZone._targetArea
  4. 调整 BoxCollider2D 大小至覆盖整个区域过渡走廊宽度(通常 2×3 或 2×4

典型布局

[区域 A]  ‖  [走廊]  ‖  [区域 B]
            ←← TriggerZone_A→B (_targetArea = CameraArea_B)
            TriggerZone_B→A (_targetArea = CameraArea_A) →→

双向过渡需要两个 TriggerZone 分别放置在走廊两端,各自指向对应区域的 CameraArea

3.4 全局 VCam Follow 绑定

Persistent 场景中两台全局 VCam 的 CinemachineCamera.Follow 须指向 Player 下的 CameraFollowTarget 子节点,而非 Player 根节点本身。
使用 Place Player 工具放置 Player 时,CameraFollowTarget 子节点会被自动创建(localPosition = 0)。

方法

  • 自动:打开 Camera Area Setup 窗口 → CameraStateController 区域 → 点击 为全局 VCam 赋值 Follow 目标(场景中必须已有 tag=Player 对象)
  • 手动:分别选中 VCamA / VCamB → CinemachineCamera 组件 → Follow 字段拖入 Player/CameraFollowTarget Transform

3.5 编辑可视区域(透视相机)

CameraArea 支持在 Scene 视图中直接定义摄像机的最大可视范围,并自动换算为限位 PolygonCollider2D 的顶点坐标。

Inspector 字段

字段 说明
_visibleBounds 摄像机应显示的最大可视矩形世界坐标Scene 视图选中时显示为黄色矩形
_cameraDepth 摄像机到场景平面Z = 0的垂直距离0 则自动读取 |transform.position.z|

Scene 视图拖拽编辑

选中 CameraArea GameObject 后Scene 视图出现:

  • 黄色矩形:可视区域(玩家在此区域内的最大可见范围)
  • 蓝色多边形:当前 PolygonCollider2D 限位边界(参考用)

矩形四条边各有一个滑动 Handle拖拽即可调整

  • 左 / 右边 Handle沿 X 轴滑动
  • 上 / 下边 Handle沿 Y 轴滑动

同步到限位区域

调整好可视区域后,在 Inspector 底部点击 「从可视区域更新限位区域(透视)」,工具根据以下公式换算限位多边形:

halfH   = depth × tan(vFOV / 2)
halfW   = halfH × aspectRatio
confiner = visibleBounds 向内收缩 (halfW, halfH)

含义相机视口边缘恰好与可视区域边框对齐。若区域小于单屏inset 后为负),限位收缩为中心点,相机固定居中。

Inspector 参数预览区实时显示 FOV来源专有 VCam → 全局 VCamA → Camera.main → 60°、深度、视口半宽 / 半高的计算值。

3.6 专有 VCam特殊区域

需要独特相机参数(如 Boss 区域特写 FOV的区域可在 CameraArea._dedicatedCamera 中指定一台独立的 CinemachineCamera

  1. 在关卡场景中新建空 GameObject挂载 CinemachineCamera(设置好 Lens、Follow、Noise 等参数)
  2. 将其拖入该 CameraArea._dedicatedCamera
  3. _dedicatedPriority(默认 20须高于全局 VCam 的激活优先级10

进入该区域时,CameraStateController 自动提升专有 VCam 优先级Cinemachine 混合切换;离开时优先级归零,全局 VCam 重新接管。


4. ScriptableObject 资产说明

4.1 CameraBlendProfileSO

创建路径Assets → Create → BaseGames → Camera → BlendProfile

字段 说明 典型值
Style 混合曲线类型EaseInOut / Linear / Cut / Custom EaseInOut
BlendTime 混合持续时间(秒) 0.5
CustomCurve Style = Custom 时使用

使用

  • 全局默认:拖入 CameraStateController._defaultBlendProfile
  • 单独区域:拖入对应 CameraArea._blendProfile(覆盖全局默认)

4.2 CameraConfigSO

创建路径Assets → Create → BaseGames → Camera → CameraConfig

字段 说明 典型值
FollowDamping 跟随阻尼(越大越迟钝) 0.15
LookAheadTime 朝向预见时间(秒) 0.3
DeadZoneSize 死区尺寸(玩家在此范围内移动相机不动) (1, 0.5)
SoftZoneSize 软区尺寸(慢速追赶) (2.5, 2)
LookDownOffset 俯视偏移(负值向下) -1.5
LookUpOffset 仰视偏移(正值向上) 1.5
DefaultImpulseStrength 默认震屏强度 0.3

CameraConfigSO 的配置值须由运行时的 CameraStateController 或相机系统读取并写入 Cinemachine 组件,具体写入逻辑取决于 CameraStateController.ApplyConfig() 的实现(如有扩展)。


5. Camera Area Setup 工具详解

菜单:BaseGames → Camera → Camera Area Setup

5.1 界面区域说明

工具栏

  • ↻ 刷新:手动重新扫描当前已加载场景
  • Place Camera Area:快捷调用 BaseGames → Scene → Place → Camera Area
  • Place Trigger Zone:快捷调用 BaseGames → Scene → Place → Camera Trigger Zone

CameraStateController 区域
显示控制器组件绑定状态。若显示"未找到"提示,说明 Persistent 场景未加载(属正常)。

图标 含义
(绿) 项目已正确配置
(红) 缺失必填项
(黄) 可选项未设置

检查项:_vcamA_vcamB(必填)、_brain(必填)、_impulseSource(可选)、_defaultBlendProfile(可选)

底部按钮:为全局 VCam 赋值 Follow 目标 → 查找 Player/CameraFollowTarget 并写入两台 VCam 的 Follow 字段。

Camera Areas 区域
为每个 CameraArea 显示一行,检查项:

字段 状态
_confinerCollider (PolygonCollider2D) 必填
_dedicatedCamera(专有 VCam 可选
_blendProfile 可选

每行可点击 修复:绑定子节点 PolygonCollider2D 自动修复 _confinerCollider 未绑定的情况。

Camera Trigger Zones 区域
列出所有 CameraTriggerZone,高亮显示 _targetArea 未绑定的项目(红色 ✗)。

5.2 典型使用流程

1. 打开窗口 BaseGames → Camera → Camera Area Setup
2. (仅首次)加载 Persistent 场景,确认 _vcamA/_vcamB/_brain 全绿
3. 在关卡场景中使用 Place Camera Area × N一个房间可放多个
4. 选中每个 CameraArea在 Scene 视图拖拽黄色可视区域边 Handle点击 [从可视区域更新限位区域(透视)]
5. 点击 [为全局 VCam 赋值 Follow 目标](自动创建 Player/CameraFollowTarget 并绑定)
6. 使用 Place Trigger Zone 添加 N 个触发器,手动绑定 _targetArea
7. 所有条目绿色 ● → 进入 Play Mode 验证

6. 验收测试用例

测试前检查清单

# 检查项 操作
1 Console 无红色 Error Window → General → Console
2 Camera Area Setup 窗口所有必填项为绿色 ● BaseGames → Camera → Camera Area Setup
3 Player 已在场景中tag = Player Hierarchy
4 Physics2D Layer 矩阵已配置 BaseGames → Tools → Validate Physics2D Layer Matrix

MT-CAM-01全局 VCam 正常跟随

目的:验证全局 VCam 激活后 CinemachineCamera 跟随玩家移动。

步骤:

  1. Persistent 场景中放置 VCamA/VCamBFollow = Player/CameraFollowTarget
  2. 关卡场景中放置一个 CameraArea,通过 CameraTriggerZoneRoomController 触发 SwitchArea
  3. Play,在 Scene 视图和 Game 视图同时观察
  4. 用 WASD/方向键移动 Player

预期结果:

检查点 期望
Game 视图相机跟随 Player 移动 玩家靠近边缘时相机平滑跟进
相机不会越出 CameraArea 的限位范围 玩家走到边角时相机贴边停止
无跳变(平滑)跟随 无抖动、跳帧

MT-CAM-02区域相机切换CameraTriggerZone

目的:验证玩家穿越触发器后全局 VCam ping-pong 平滑过渡到目标区域。

步骤:

  1. 场景中放置两个 CameraAreaA、B各有独立 PolygonCollider2D 限位
  2. 在两区域之间放置两个 CameraTriggerZone(各自 _targetArea 互指)
  3. Play,引导 Player 穿越触发区进入区域 B

预期结果:

检查点 期望
穿越触发器后 Game 视图开始混合过渡 相机平滑从 A 过渡到 B非切割
过渡时长约等于 CameraBlendProfileSO.BlendTime 与 SO 设置一致(默认 0.5s
过渡后相机限位在 CameraArea_B 的边界内 玩家无法把相机带出 B 的限位范围
反向穿越触发器后相机切回 A 同上,反向过渡

MT-CAM-03CinemachineConfiner2D 边界限位

目的:验证 CinemachineConfiner2D 正确将相机限制在 CameraArea 限位范围内。

步骤:

  1. 打开关卡场景,确认 CameraArea._confinerCollider 已绑定,且 CameraStateController 已调用 SwitchArea
  2. Play,将 Player 移动到房间的各个角落和边缘

预期结果:

检查点 期望
相机在所有方向均不超出 PolygonCollider2D 多边形范围 无越界
小房间(相机视口 > 房间)时相机居中,不晃动 稳定居中

常见失败原因

  • CameraArea._confinerCollider 未绑定 → 打开 Camera Area Setup 点击修复
  • PolygonCollider2D 顶点数量少于 3 → 确认 _confinerCollider 路径顶点完整

MT-CAM-04屏幕抖动CinemachineImpulseSource

目的:验证调用 ICameraService.TriggerImpulse 时 Game 视图画面抖动。

步骤:

  1. 确认 CameraStateController._impulseSource 已绑定
  2. Play
  3. 在 Console 执行(或通过游戏内事件触发):
    ServiceLocator.Get<ICameraService>().TriggerImpulse(0.5f);
    
    或让玩家受到一次伤害(若伤害系统已接入抖动调用)

预期结果:

检查点 期望
Game 视图画面发生轻微抖动后恢复稳定 抖动时长约 0.20.4s,幅度可见
无 Console 错误 无 NullReferenceException

MT-CAM-05初始场景无 CameraStateController 时安全降级

目的:验证场景中未加载 Persistent 场景时,CameraTriggerZone 不崩溃。

步骤:

  1. 单独打开关卡场景(不加载 Persistent.unity
  2. Play,移动 Player 穿越 CameraTriggerZone

预期结果:

检查点 期望
无 NullReferenceException ServiceLocator.GetOrDefault<ICameraService>() 返回 null 时跳过
Console 可能有黄色 Warning服务未注册 无红色 Error

MT-CAM-06多场景加载时相机状态正确恢复

目的:验证通过 SceneLoader 加载新场景时,CameraStateController 正确切换到新场景首个 CameraArea

步骤:

  1. 以 Persistent + Level_01 双场景启动
  2. Play,触发场景加载切换到 Level_02
  3. Level_02 加载完成后观察相机

预期结果:

检查点 期望
Level_02 的 RoomController 调用 SwitchArea 后相机切换正确 无黑屏、无旧场景相机残影
旧场景 CameraArea 随场景卸载,全局 VCam 状态不受干扰 无相机混合错误

注意:全局 VCam 常驻 Persistent 场景,CinemachineConfiner2D.BoundingShape2DSwitchArea 时动态更新, 旧场景卸载后引用会变为 null须确保 SwitchArea 在新场景 CameraArea 可用后再调用。


7. 常见问题排查

现象 原因 解决
Game 视图相机不动(黑屏或固定位置) 全局 VCam Follow 未绑定 Camera Area Setup → 为全局 VCam 赋值 Follow 目标
相机追赶卡顿/震颤 CinemachineConfiner2D.BoundingShape2D 未绑定或碰撞体顶点有误 确认 CameraArea._confinerCollider 已绑定PolygonCollider2D 顶点数 ≥ 3
进入区域后限位未更新(仍在旧区域限位内) CameraArea._confinerCollider 为空,ConfigureSlot 跳过了更新 打开 Camera Area Setup 修复 _confinerCollider 绑定
场景中有多个 CinemachineBrain Persistent 场景外又添加了含 Camera 组件的对象 仅 Main Camera 上保留一个 Brain
过渡时画面闪切而非混合 CameraBlendProfileSO.BlendTime = 0 或 Style = Cut 检查 BlendProfile 并将 BlendTime 设置为 > 0
CameraStateController 未找到Console 错误) Persistent 场景未加载 确认 Build Settings 中 Persistent.unity 第一位;开发测试用 SceneManager.LoadScene("Persistent", Additive)
触发器无响应(玩家穿越后相机不切) CameraTriggerZone._targetArea 未绑定,或 _playerTag 不匹配 检查 _targetArea 是否已拖入 CameraArea;确认 Player Tag = "Player"
Camera Area Setup 窗口列表为空 场景未保存或 DomainReload 后未刷新 点击窗口内 ↻ 刷新 按钮
专有 VCam 不切换 _dedicatedPriority ≤ 全局激活优先级(默认 10 _dedicatedPriority 设置为 > 10默认 20 已满足)