地图编辑、导出与双端加载 private
地图编辑、导出与双端加载
回答“地图怎样从 Unity 场景变成前后端共享数据,以及一次地图修改如何正确发布”。
6. 地图编辑、导出与双端加载
6.1 作者态与运行态
地图编辑场景中的 GameObject + Extension 是“作者态”。导出后会成为不依赖场景层级的 IMapElement 树,客户端和服务端分别转换为自己的运行时实体。
常用组件:
MapRoot、MapTemplate:地图根和可复用模板。ObjectSpawnPoint:通用出生点。MonsterOverrideExtension:巡逻点、搜索/追击范围、延迟、掉落标记等覆盖项。MonsterGroup、MonsterRandomGroup、波次/陷阱组。RangeTriggerExtension、GroupTriggerExtension。MiniMapExtension、NavMeshLink和导航 Prefab。
6.2 导出菜单与产物
Assets/Maps/Scripts/MapBaker.cs 注册:
Assets/Map/ZipCurrMapDataAssets/Map/ZipSelectedMapDataAssets/Map/ZipAllMapData- 对应的
AutoCopy版本 Assets/Map/CopyProjectMapDataToServer- 校验入口
Assets/Map/MapDataCheckAll
| 产物 | 用途 |
|---|---|
Assets/Maps/Resources_moved/Maps/Data/{name} | 客户端地图二进制 |
../Maps/Data/{name} | 外部服务端地图目录 |
../ClientMapData/Data/{name}.json | 可读调试数据 |
../Maps.zip | 服务端地图包 |
AssetsMapPath.bytes | 地图 GUID 到路径映射 |
bakeid.txt | 烘焙版本/同步标识 |
MapBakerInfo.txt 决定复制到服务端的位置。换机器后先确认它不是旧绝对路径。
flowchart TD
A[遍历场景根节点] --> B[识别 Template/Spawner/Trigger/Nav]
B --> C[MapElementBaker 转 IMapElement 树]
C --> D[组合 Transform 和 GUID 引用]
D --> E[提取 NavMesh Triangulation / Link]
E --> F[BinaryMapFormatter 序列化]
F --> G[客户端 Maps/Data]
F --> H[服务端 Maps/Data 或 Maps.zip]
D --> I[AssetsMapPath.bytes]
F --> J[调试 JSON]
NavMesh.CalculateTriangulation() 也用于检查导航烘焙结果。提交前运行 MapDataCheckAll,重点检查重复 GUID、随机组空权重、怪物 ID、模板引用和未烘焙导航。
6.3 客户端加载
服务端通过 SceneInfo 下发地图名、章节/世界/关卡、模板下标、随机种子、SceneGuid 和时间。
CS_LoadServerLevelDataSystem 收到后:
- 更新服务器时间基准并按玩法切换
MapAdapter控制器。 - 用
CfgAssetsPath查Maps/Data/{name}。 - 触发
MapChangeLevelByIndicesEvent。 MapProcessor反序列化并递归展开 Transform、Group、Template。- 地图就绪后发
LoadSceneSuc;主角创建完成后发InitHeroSuc。
服务端选择的 TemplateIndices 和 randomSeed 保证多人随机地图一致,客户端不能自行再抽一次。
6.4 服务端加载
Battle 启动时 MapDatas 将 Maps/Data/*.bytes 和 Maps/Database/AssetsMapPath.bytes 载入内存,也支持解压 Maps.zip。Scene 按地图名取得 bytes,交给服务端 BinaryMapFormatter 和 MapProcessor。
服务端 ProcessMonsterSpawner() 直接创建权威 Monster,设置位置、旋转、覆盖数据、延迟和 SpawnSignal,初始 inactive,再由 Scene/触发逻辑激活。只更新客户端地图而不更新服务器,会造成位置、随机模板、触发器和怪物集合不一致。
6.5 地图修改 SOP
- 在
Assets/Maps/EditorScenes打开目标场景。 - 修改元素,确保新对象 GUID 唯一、模板引用有效。
- 烘焙 Unity NavMesh,检查
NavMeshLink两端。 - 运行
Assets/Map/MapDataCheckAll。 - 导出当前地图,需要联调时 AutoCopy 或明确复制服务端产物。
- 确认客户端、服务端和
AssetsMapPath.bytes来自同次导出。 - 重启或热载 Battle 地图数据;仅重进客户端不一定刷新服务端内存。
- 对照服务端和客户端的 mapName、SceneGuid、randomSeed、templateIndices。