Files
zeling_v2/Docs/Practices/World_Region_Room_CameraZone.md

7.5 KiB
Raw Permalink Blame History

世界层级划分规范:大地图区域 / 房间 / 摄像机区域

适用范围BaseGames.WorldBaseGames.CameraBaseGames.World.Map 关联代码RoomControllerRoomTransitionMapRoomDataSOMapDatabaseSORoomCameraCameraTriggerZoneCameraStateController


一、三层结构总览

大地图区域Region          ← 纯分类标签,无独立 Scene
    └── 房间Room          ← 一个 Addressable Unity 场景,加载/卸载的最小单元
            └── 摄像机区域Camera Zone  ← Room 内部的视野子区域

这三层粒度严格单向包含,不允许跨层引用(如 CameraZone 不应直接引用 Region 数据)。


二、大地图区域Region

定义

Region 在代码中仅体现为 MapRoomDataSO.RegionIdstring 字段),没有独立的 Scene 或 GameObject。 它是一个纯粹的分类标签,由各子系统按需读取。

命名约定

Forest、Ruins、Underground、Castle、Abyss ...

使用 PascalCase 英文单词,与 MapRoomDataSO 资产文件路径保持一致:

Assets/ScriptableObjects/Map/Room_Forest_01.asset   → RegionId = "Forest"
Assets/ScriptableObjects/Map/Room_Ruins_03.asset    → RegionId = "Ruins"

各系统对 RegionId 的用途

系统 行为
MapPanel RegionId 分组格子,可染不同底色
BGMController 监听 EVT_RoomEntered,比较前后 RegionId 决定是否淡入淡出新 BGM
DifficultyScalerSO 可按 Region 配置不同难度曲线

跨区域事件(已实现)

MapManager.OnRoomEntered 每次进房时比较 RegionId,区域变化时广播 _onRegionChangedStringEventChannelSO,建议资产命名 EVT_RegionChanged)。在 Inspector 中将对应的 StringEventChannelSO 资产拖入 _onRegionChanged 槽位即可启用。

订阅示例:

// BGMController — 区域切换时淡入新 BGM
_onRegionChanged?.Subscribe(regionId => PlayBGMForRegion(regionId)).AddTo(_subs);

// MapPanel — 可选:高亮当前区域格子
_onRegionChanged?.Subscribe(_ => RefreshRegionHighlight()).AddTo(_subs);

也可通过接口直接查询当前区域(无需订阅事件):

var region = ServiceLocator.Get<IMapService>().CurrentRegionId;

三、房间Room

定义

Room = 一个 Addressable Unity 场景,通过 SceneLoader 以 Additive 模式加载,是地图加载/卸载的最小单元。

每个 Room 场景必须包含:

  • RoomController(挂在 [RoomRoot] 下):持有 _roomId_spawnPoints[]_roomCamera
  • 至少一个 PlayerSpawnPointTransitionId 与上游 RoomTransition._targetTransitionId 对应)
  • 对应的 MapRoomDataSO 资产(RoomId_roomId 一致)

划分原则

应该单独成一个 Room 的情况:

情况 原因
地形拓扑彻底断开(门、竖井、地下入口) 自然的 Additive 场景边界
有独立存档点(SavePoint 复活逻辑依赖 roomId 定位存档点
Boss 竞技场 IsBossRoom = trueGameManager 监听 EVT_BossFightStarted
商店 / 特殊 NPC 房间 IsShop = true,地图图标独立标记
独立 BGM 区域 RegionId 变化或同区域内 BGM 不同
地图格子单元(GridPosition 有意义的独立位置) MapPanel 以格为单位渲染

不要过度切分的情况:

情况 建议
无地图意义的短走廊 合并到相邻功能房间,避免触发无意义的 Additive 加载/卸载
同一视野无特殊逻辑的连续平台 合并,减少 RoomTransition 触发频率

命名约定

Room_{RegionId}_{序号两位}
示例Room_Forest_01、Room_Ruins_03、Room_Boss_Forest_01

Addressable Key 与场景名保持一致,MapRoomDataSO.RoomId 与两者均一致。


四、摄像机区域Camera Zone

定义

Camera Zone = Room 内部的视野子区域,由以下组件组合定义:

组件 职责
RoomCamera 包装 CinemachineCamera,持有该区域的 RoomVisibleArea、偏移、混合配置
RoomVisibleArea PolygonCollider2D,作为 Cinemachine Confiner2D 的限位边界
CameraTriggerZone BoxCollider2D 触发器,玩家进入时调用 ICameraService.SwitchRoom(targetCamera)

CameraStateController 同时只激活一个 RoomCamera,切换时旧相机 Priority = 0(停用),新相机 Priority = 15(激活)。

划分原则

需要新建 Camera Zone 的情况:

情况 配置方式
房间内有高低落差或宽窄通道 各区域放独立 CameraTriggerZone + RoomCamera(独立 RoomVisibleArea
Boss 竞技场入场锁定视野 进入 Arena 触发器切换到关闭 Follow 的固定 RoomCamera
可选路径(上路/下路)视野不同 每条路各放 1 个触发器

不需要额外 Camera Zone 的情况:

情况 配置方式
房间完全平坦无特殊视野需求 RoomController._roomCamera 1 个,无需 CameraTriggerZone

Room 内 Camera Zone 的标准层级结构

[Room_Forest_01]
├── RoomController (_roomCamera → Cam_Main)
├── Cameras/
│   ├── Cam_Main          (RoomCamera + RoomVisibleArea) ← 入口默认视野
│   ├── Cam_Narrow        (RoomCamera + RoomVisibleArea) ← 密道区
│   └── Cam_Arena         (RoomCamera + RoomVisibleArea) ← Boss 场
├── Triggers/
│   ├── Trigger_Narrow    (CameraTriggerZone → Cam_Narrow)
│   └── Trigger_Arena     (CameraTriggerZone → Cam_Arena)
├── SpawnPoints/
│   ├── SpawnPoint_Entry  (transitionId: "entry_main")
│   └── SpawnPoint_Arena  (transitionId: "entry_arena")
└── [GameplayObjects] ...

混合配置复用

不同 Camera Zone 切换时的过渡动画通过 CameraBlendProfileSO 配置:

Assets/ScriptableObjects/Camera/Blend_Default.asset     → EaseInOut 0.5s(大多数房间切换)
Assets/ScriptableObjects/Camera/Blend_BossArena.asset   → Cut 0sBoss 入场瞬切)
Assets/ScriptableObjects/Camera/Blend_Slow.asset        → EaseInOut 1.5s(过场/剧情用)

五、完整示例

Region: Forest森林区域
│
├── Room: Room_Forest_01入口区
│     RoomCamera: 1个无子区域
│     RoomTransition → Room_Forest_02右侧出口
│     RoomTransition → Room_Ruins_01跨区域出口需钥匙
│
├── Room: Room_Forest_02主干道 + 密道)
│     RoomCamera: Cam_Main平台区宽视野
│     RoomCamera: Cam_Narrow树干夹缝窄限位
│     CameraTriggerZone → Cam_Narrow进入密道触发
│     RoomTransition → Room_Forest_Boss_01
│
└── Room: Room_Forest_Boss_01Boss 竞技场)
      RoomCamera: Cam_Entrance进门走廊
      RoomCamera: Cam_ArenaBoss战固定锁定视野
      CameraTriggerZone → Cam_Arena进入竞技场触发
      IsBossRoom = true → GameManager 监听 EVT_BossFightStarted

六、编辑器工具

  • BaseGames → Camera → Room Camera Setup:扫描当前场景所有 RoomCamera / CameraTriggerZone,显示绑定状态并提供一键修复。新建 Room 后务必用此工具检查是否存在未绑定的 Camera Zone。
  • MapDatabaseSO.GetRoom(roomId)已内置懒加载字典索引O(1) 查找),无需手动维护索引。