# 手动测试 12 · 区域相机系统 > **测试类型**:Unity Editor 手动测试(Play Mode) > **覆盖模块**:`CameraArea`、`CameraTriggerZone`、`CameraStateController`、`CinemachineConfiner2D`、`CameraBlendProfileSO` > **前置文档**:`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. [系统架构说明](#1-系统架构说明) 2. [Persistent 场景配置(CameraStateController)](#2-persistent-场景配置cameraStatecontroller) 3. [关卡场景配置(CameraArea + CameraTriggerZone)](#3-关卡场景配置cameraarea--cameratriggerzone) 4. [ScriptableObject 资产说明](#4-scriptableobject-资产说明) 5. [Camera Area Setup 工具详解](#5-camera-area-setup-工具详解) 6. [验收测试用例](#6-验收测试用例) 7. [常见问题排查](#7-常见问题排查) --- ## 1. 系统架构说明 ``` Persistent.unity └── [Camera] └── CameraStateController ExecutionOrder = -100 组件: CameraStateController │ _vcamA → VCamA(全局虚拟相机 A) │ _vcamB → VCamB(全局虚拟相机 B) │ _lookSystem → CameraLookSystem 节点 组件: CinemachineBrain ← 实际渲染相机(随 Main Camera 放置) 组件: CinemachineImpulseSource ← 屏幕抖动信号源 ├── CameraLookSystem ← 运行时由 SetFollowTarget() 赋值基准目标 │ 组件: CameraLookSystem 双轴窥视偏移 + 速度门控;输出 VirtualTarget ├── VCamA │ 组件: CinemachineCamera Follow = CameraLookSystem.VirtualTarget(运行时自动赋值) │ 组件: CinemachinePositionComposer Body 跟随组件;初始值与 CameraArea 默认值对齐 │ 组件: CinemachineConfiner2D ← 由 CameraStateController 动态更新 BoundingShape2D │ 组件: CameraAxisLockExtension 锁定 X 或 Y 轴(竖井 / 走廊场景) │ 组件: CameraAsymmetricDampingExtension 非对称 Y 阻尼(下落快恢复,起跳慢追赶) │ 组件: CameraAdaptiveLookaheadExtension 速度自适应 Lookahead(移动快 → 预见更多) └── VCamB 组件: CinemachineCamera Follow = CameraLookSystem.VirtualTarget(运行时自动赋值) 组件: CinemachinePositionComposer 同 VCamA 组件: CinemachineConfiner2D ← 由 CameraStateController 动态更新 BoundingShape2D 组件: CameraAxisLockExtension 组件: CameraAsymmetricDampingExtension 组件: CameraAdaptiveLookaheadExtension 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. 玩家进入 `CameraTriggerZone` → `OnTriggerEnter2D` 调用 `ICameraService.SwitchArea(targetArea)` 2. `CameraStateController.SwitchArea` → 应用 `BlendProfile` 到 `CinemachineBrain.DefaultBlend` - **无专有 VCam**:配置非活跃全局 VCam 的 `CinemachineConfiner2D.BoundingShape2D` → 提升其优先级至 10 → 降低旧 VCam 优先级至 0(ping-pong),Cinemachine Brain 自动触发混合过渡 - **有专有 VCam**:提升 `_dedicatedCamera` 优先级至 `_dedicatedPriority`(默认 20),高于全局 VCam,Cinemachine 自动切换 --- ## 2. Persistent 场景配置(CameraStateController) ### 2.1 组件放置 在 Persistent 场景的 `[Camera]` 下建立以下节点结构: | GameObject | 挂载组件 | 说明 | |-----------|---------|------| | `[CameraController]` | `CameraStateController`、`CinemachineBrain`、`CinemachineImpulseSource` | ExecutionOrder = -100 | | `CameraLookSystem` | `CameraLookSystem` | 双轴窥视偏移(垂直+水平)+ 速度门控;输出 `VirtualTarget` 供 VCam 跟随;拖入 `CameraStateController._lookSystem` | | `VCamA` | `CinemachineCamera`、**`CinemachinePositionComposer`**、`CinemachineConfiner2D`、`CameraAxisLockExtension`、`CameraAsymmetricDampingExtension`、`CameraAdaptiveLookaheadExtension` | 全局虚拟相机 A;**PositionComposer 是 Body 组件,必须存在**;拖入 `CameraStateController._vcamA` | | `VCamB` | `CinemachineCamera`、**`CinemachinePositionComposer`**、`CinemachineConfiner2D`、`CameraAxisLockExtension`、`CameraAsymmetricDampingExtension`、`CameraAdaptiveLookaheadExtension` | 全局虚拟相机 B;同 VCamA;拖入 `CameraStateController._vcamB` | > **注意**:`CinemachineBrain` 须挂在附有 `Camera` 组件(Main Camera)的 GameObject 上, > 否则 Cinemachine 无法驱动视口渲染。两台全局 VCam 初始优先级均为 0,由 `CameraStateController` 在运行时动态管理。 ### 2.2 字段绑定清单 打开 **Camera Area Setup** 窗口(`BaseGames → Camera → Camera Area Setup`), 在 **CameraStateController** 区域确认以下项目全为绿色 ●: | 字段 | 期望状态 | |------|---------| | `_vcamA` (CinemachineCamera) | ● 已绑定 | | `_vcamB` (CinemachineCamera) | ● 已绑定 | | `_brain` (CinemachineBrain) | ● 已绑定 | | `_lookSystem` (CameraLookSystem) | ● 已绑定 | | `_impulseSource` (CinemachineImpulseSource) | ◌ 可选;用于屏幕抖动 | | `_defaultBlendProfile` (CameraBlendProfileSO) | ◌ 可选;未设置则无混合过渡 | --- ## 3. 关卡场景配置(CameraArea + CameraTriggerZone) ### 3.1 添加 CameraArea **方式 A:使用快速放置工具**(推荐) 1. 菜单 `BaseGames → Scene → Place → Camera Area` 2. 工具自动创建以下节点结构: ``` CameraArea ├── CameraArea(组件,_confinerCollider 已绑定) └── PolygonCollider2D(默认矩形 24×12,isTrigger = true,定义限位区域) ``` 3. 打开 **Camera Area Setup** 窗口,点击 **为全局 VCam 赋值 Follow 目标** (工具会自动在 Player 下查找或创建 `CameraFollowTarget` 子节点,绑定到两台全局 VCam)。 4. 手动调整子节点 `PolygonCollider2D` 顶点定义限位范围。 **方式 B:手动创建** 1. 新建空 GameObject,命名如 `CameraArea_A` 2. 挂载 `CameraArea`(BaseGames.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") └── BoxCollider2D(isTrigger = 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**, 而是指向 `CameraLookSystem` 组件在运行时生成的 **`[CameraLookTarget]` 虚拟目标节点**。 该节点由 `CameraStateController.SetFollowTarget(Transform)` 在玩家注册时自动创建并赋值, 其世界位置 = Player 基准目标位置 + 当前窥视偏移(`CameraLookSystem` 的双轴输出)。 > **不要在 Inspector 中手动把 VCam.Follow 拖到 Player 本身或 Player/CameraFollowTarget。** > `SetFollowTarget` 会在运行时覆盖,且直接指向 Player 会绕过窥视偏移计算。 **工具支持**: **Camera Area Setup** 窗口 → **为全局 VCam 赋值 Follow 目标** 按钮 → 该按钮仅用于调试回退(绕过 LookSystem,直指 Player/CameraFollowTarget)。 正式流程请通过 `ICameraService.SetFollowTarget(playerTransform)` 注册,由系统自动处理。 --- ### 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 > ⚠ **Legacy / 已废弃**:`CameraConfigSO` 是早期相机系统的配置资产,现已不再被 `CameraStateController` 读取或应用。 > 当前架构直接通过 `CameraArea` 字段(`ScreenPosition`、`DeadZoneSize`、`LookaheadTime`、`DampingDown`、`DampingUp` 等)在 `ConfigureSlot` 时写入 Cinemachine 组件,无需此 SO。 > 若项目中仍存在 `CameraConfigSO` 资产,可安全忽略或删除。 ~~**创建路径**:`Assets → Create → BaseGames → Camera → CameraConfig`~~ | 字段 | 说明 | 典型值 | |------|------|--------| | `FollowDamping` | ~~跟随阻尼~~ | — | | `LookAheadTime` | ~~朝向预见时间~~ | — | | `DeadZoneSize` | ~~死区尺寸~~ | — | | `SoftZoneSize` | ~~软区尺寸~~ | — | | `LookDownOffset` | ~~俯视偏移~~ | — | | `LookUpOffset` | ~~仰视偏移~~ | — | | `DefaultImpulseStrength` | ~~默认震屏强度~~ | — | > `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`(必填)、`_lookSystem`(必填)、`_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/VCamB,`Follow = Player/CameraFollowTarget` 2. 关卡场景中放置一个 `CameraArea`,通过 `CameraTriggerZone` 或 `RoomController` 触发 `SwitchArea` 3. 按 **Play**,在 Scene 视图和 Game 视图同时观察 4. 用 WASD/方向键移动 Player **预期结果:** | 检查点 | 期望 | ✓ | |--------|------|---| | Game 视图相机跟随 Player 移动 | 玩家靠近边缘时相机平滑跟进 | ☐ | | 相机不会越出 CameraArea 的限位范围 | 玩家走到边角时相机贴边停止 | ☐ | | 无跳变(平滑)跟随 | 无抖动、跳帧 | ☐ | --- ### MT-CAM-02:区域相机切换(CameraTriggerZone) **目的**:验证玩家穿越触发器后全局 VCam ping-pong 平滑过渡到目标区域。 **步骤:** 1. 场景中放置两个 `CameraArea`(A、B),各有独立 `PolygonCollider2D` 限位 2. 在两区域之间放置两个 `CameraTriggerZone`(各自 `_targetArea` 互指) 3. 按 **Play**,引导 Player 穿越触发区进入区域 B **预期结果:** | 检查点 | 期望 | ✓ | |--------|------|---| | 穿越触发器后 Game 视图开始混合过渡 | 相机平滑从 A 过渡到 B(非切割) | ☐ | | 过渡时长约等于 `CameraBlendProfileSO.BlendTime` | 与 SO 设置一致(默认 0.5s) | ☐ | | 过渡后相机限位在 CameraArea_B 的边界内 | 玩家无法把相机带出 B 的限位范围 | ☐ | | 反向穿越触发器后相机切回 A | 同上,反向过渡 | ☐ | --- ### MT-CAM-03:CinemachineConfiner2D 边界限位 **目的**:验证 `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 执行(或通过游戏内事件触发): ```csharp ServiceLocator.Get().TriggerImpulse(0.5f); ``` 或让玩家受到一次伤害(若伤害系统已接入抖动调用) **预期结果:** | 检查点 | 期望 | ✓ | |--------|------|---| | Game 视图画面发生轻微抖动后恢复稳定 | 抖动时长约 0.2–0.4s,幅度可见 | ☐ | | 无 Console 错误 | 无 NullReferenceException | ☐ | --- ### MT-CAM-05:初始场景无 CameraStateController 时安全降级 **目的**:验证场景中未加载 Persistent 场景时,`CameraTriggerZone` 不崩溃。 **步骤:** 1. 单独打开关卡场景(不加载 Persistent.unity) 2. 按 **Play**,移动 Player 穿越 `CameraTriggerZone` **预期结果:** | 检查点 | 期望 | ✓ | |--------|------|---| | 无 NullReferenceException | `ServiceLocator.GetOrDefault()` 返回 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.BoundingShape2D` 在 `SwitchArea` 时动态更新, > 旧场景卸载后引用会变为 null,须确保 `SwitchArea` 在新场景 `CameraArea` 可用后再调用。 --- ## 7. 常见问题排查 | 现象 | 原因 | 解决 | |------|------|------| | Game 视图相机不动(黑屏或固定位置) | 全局 VCam `Follow` 未绑定 | `ICameraService.SetFollowTarget(player)` 注册玩家;或 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 已满足) | | Camera Area Setup 中 `_lookSystem` 红色 ✗ | `CameraStateController._lookSystem` 未绑定 | 将 Persistent 场景 `[Camera]/CameraLookSystem` 节点拖入该字段;或重新运行 SceneScaffoldTools | | 按住方向键相机偏移不出现(窥视无效) | `CameraLookSystem._baseTarget` 未设置 | 确认 `ICameraService.SetFollowTarget(player)` 在玩家 Awake/Start 后调用 | | 下落时相机跟随过慢(非对称阻尼异常) | `CameraAsymmetricDampingExtension` 未挂到 VCamA/VCamB,或 `DampingDown` 未被 `ConfigureSlot` 写入 | 确认两台 VCam 已挂载该扩展;检查 `CameraArea._dampingDown` > 0 | | 高速移动时 Lookahead 不变化 | `CameraAdaptiveLookaheadExtension` 未挂到 VCamA/VCamB,或 `SetConfiguredMax` 未被调用 | 确认两台 VCam 已挂载该扩展;检查 `ConfigureSlot` 代码路径正常执行 |