世界分区
World Partition
世界分区 (World Partition) 是 UE5 的自动数据管理与基于距离的关卡流送 (Level Streaming) 系统:整个世界存为一个持久关卡,按可配置的运行时网格划分为单元格 (Cell),由流送源 (Streaming Source,默认是玩家控制器) 按距离加载/卸载。它配合一 Actor 一文件 (One File Per Actor, OFPA) 支持多人协作编辑,用数据层 (Data Layers) 按玩法状态切换内容,用分层细节层次 (Hierarchical Level of Detail, HLOD) 在远处以代理网格显示未加载的单元格。
为什么要它
过去做大地图要手动把关卡切成子关卡,再用关卡流送按玩家位置加载;这会导致多人共享文件冲突,也难以在上下文中查看整个世界。World Partition 用单一持久关卡 + 自动网格单元格取代手动子关卡。(World Partition)
运行时流送模型
下图表示运行时的决策:每个单元格是否加载,取决于它与各流送源的距离是否在网格的加载范围内;未加载单元格在远处由 HLOD 代理显示;运行时数据层再对其中的 Actor 做开关。
flowchart TB
SS["流送源<br/>PlayerController / Streaming Source 组件"] --> Q{"单元格在 Loading Range 内?"}
Q -- "是" --> L["加载单元格中的 Actor"]
Q -- "否" --> H["显示该区域的 HLOD 代理网格"]
L --> D{"Actor 所属运行时数据层状态"}
D -- Activated --> V["加载且可见"]
D -- Loaded --> NV["加载但不可见"]
D -- Unloaded --> X["不加载"]图中流程从上到下依次是“空间筛选 → 远景替代 → 玩法层筛选”。(World Partition、World Partition - Data Layers、World Partition - HLOD)
运行时网格(World Settings 中)主要参数:Cell Size(官方示例 256 m)、Loading Range(示例半径 768 m)、Block on Slow Streaming(单元格加载跟不上时阻塞)、Priority。默认提供一个 2D Runtime Hash 网格,多于一个网格可能损害性能;推荐设置可参考 City Sample 的 Big City 地图。(World Partition)
流送源:每个 PlayerController 默认是流送源;还可以用 World Partition Streaming Source 组件在任意位置加载,官方例子是传送——先在目的地激活流送源,单元格加载完(Is Streaming Completed)再传送,然后关闭它,原位置的单元格随之卸载。组件可指定目标网格、目标 HLOD 层、形状、优先级,以及目标状态 Loaded/Activated(多源相交时取最高)。(World Partition)
Actor 设置:Is Spatially Loaded 开启时 Actor 随流送源范围加载;关闭则(只要所属数据层未禁用)始终加载,适合环境背景、管理器。引用其他 Actor 的 Actor 会被打包在一起同时加载。(World Partition)
这本质上是把世界按均匀网格做空间划分,再以“到观察者的距离”做加载判定,可与 空间数据结构 中的均匀网格、剔除技术 中的距离剔除对照理解;渲染层面的大场景技术见 大场景渲染与虚拟纹理。
编辑器侧:OFPA 与区域加载
- 一 Actor 一文件 (OFPA):每个 Actor 存成独立文件,修改 Actor 不必签出关卡文件,减少团队冲突。(World Partition)
- 打开大世界时默认整体未加载,只加载非空间加载的 Actor;在 World Partition 编辑器窗口框选区域加载,或放置 Location Volume 定义可重复加载的区域。生成小地图 (Minimap) 需开启虚拟纹理支持。(World Partition)
- 已有关卡可用 Tools > Convert Level 或
WorldPartitionConvertCommandlet转换。(World Partition) - 坑:关卡蓝图 (Level Blueprint) 中引用的 Actor 会被标记为始终加载 (Always Loaded),因此官方更推荐用蓝图类。(World Partition)
数据层 (Data Layers)
数据层替代旧的 Layers 系统,分为项目级的数据层资产 (Data Layer Asset)(名称、类型、调试色)和世界级的数据层实例 (Data Layer Instance)——同一资产可以在不同世界有不同实例属性。(World Partition - Data Layers)
| 类型 | 用途 |
|---|---|
| 编辑器数据层 (Editor) | 组织内容:美术可只看环境、不碰玩法触发器 |
| 运行时数据层 (Runtime) | 用蓝图/C++ 切换状态驱动玩法:任务、进度、活动、关卡转换(如《古代山谷》的光明/黑暗世界) |
运行时状态有 Unloaded、Loaded(加载但不可见)、Activated(加载且可见),通过 UDataLayerSubsystem::SetDataLayerInstanceRuntimeState 设置。官方示例代码注明:客户端-服务器模式下只有服务器能激活数据层(用 HasAuthority() 判断,见 网络复制与 RPC)。(World Partition - Data Layers)
性能警告:一次通过数据层加载过多资产会有性能问题;被大量运行时数据层实例共用的资产会降低流送性能,需密切监控。数据层的标签与 ID 存在 WorldDataLayer 文件中,改名只改标签、删层只改该文件,不必重存 Actor。(World Partition - Data Layers)
HLOD:未加载区域的远景
远处不可交互的山、树、悬崖在单元格卸载后仍需可见。World Partition 的 HLOD 用 HLOD 层 (HLOD Layer) 资产组织静态网格 Actor,生成单个代理网格与材质,用于显示未加载单元格、减少每帧绘制调用 (Draw Call)、提升性能。(World Partition - HLOD)
| 层类型 | 做法 | 适用 |
|---|---|---|
| Instancing | 替换为实例化静态网格 (ISM),使用各资产最低 LOD | 树木、植被等 Imposter 类 |
| Merged Mesh | 合并为一个代理网格(可合并材质) | 建筑群 |
| Simplified Mesh | 合并后再做网格简化(可用 Merge Distance 封闭门窗等缝隙) | 远景大体量结构 |
Actor 需设为静态 (Static) 并分配到 HLOD 层(Actor 细节面板、数据层的默认 HLOD 层或 World Settings 默认层),再用 Build HLODs 或 WorldPartitionHLODsBuilder 构建;源 Actor 未变化时不会重建。HLOD 层可设置父层形成层级,也可设为始终加载。调试可用 wp.Runtime.HLOD 0 关闭 HLOD 显示。(World Partition - HLOD、World Partition)
HLOD 是 细节层次 思想在“多个对象合并”层面的推广:单个网格的 LOD 减少三角形,HLOD 再把许多对象合并以减少绘制调用。
取舍与常见坑
| 问题 | 说明 |
|---|---|
| 网格参数 | Cell 太小→单元格多、调度开销大;Loading Range 太小→近处出现空洞或频繁阻塞 |
| 多网格 | 官方提示多于一个运行时网格可能损害性能 |
| 关卡蓝图引用 | 被引用 Actor 变为始终加载 |
| 数据层滥用 | 资产被过多运行时数据层共用会拖慢流送 |
| 传送/快速移动 | 先用流送源组件预加载目标区域 |
| HLOD 过期 | 修改源网格/材质后需重新构建 |
| 多人 | 运行时数据层仅服务器可激活 |
调试命令:wp.Runtime.ToggleDrawRuntimeHash2D/3D(显示网格与加载状态)、wp.Runtime.OverrideRuntimeSpatialHashLoadingRange、wp.Runtime.MaxLoadingLevelStreamingCells(限制并发加载单元格数)、wp.DumpDatalayers 等。(World Partition、World Partition - Data Layers)关卡之外的单个资产按需加载见 资产管理与异步加载;大规模人群等实体模拟可结合 MassEntity 数据导向框架。
GEA 的视角:世界块与编辑器图层(卷 II 16.1.2、16.4.1)
- 为什么分块:GEA 认为除最小的游戏外都要把世界分成"世界块",理由是内存限制、控制游戏流程和分工;开放世界只是营造"无缝"的假象,并用 LOD 降低内存和提升性能(卷 II 16.1.2)。世界分区把这种划分自动化为运行时网格,HLOD 对应 GEA 说的 LOD 手段(这是对比归纳)。
- 按层存取避免冲突:GEA 指出,如果编辑器能单独加载和保存图层(灯光一层、背景几何一层、AI 角色一层),多个团队就能同时编辑同一世界块而不冲突(卷 II 16.4.1.5)。本页的 OFPA 用"每个 Actor 一个文件"在更细的粒度上解决同一问题;编辑器数据层则对应 GEA 说的"隐藏无关元素、减少杂乱"的图层用途(这是对比归纳)。
- 目标与块松耦合:GEA 主张玩家目标与世界块之间保持松耦合,以便独立修改(卷 II 16.1.3);运行时数据层按任务、进度切换内容,是把目标状态映射到世界内容的一种方式(这是对比归纳)。
详见 游戏世界与游戏对象 和 数据驱动与游戏世界编辑器。
GEA 第 17 章的补充:从气闸到细粒度流送(卷 II 17.4.1–17.4.3)
GEA 第 17 章描述了世界流送的演进,可作为本页的背景,详见 游戏世界的加载与流送:
- 一次一关、栈分配器(常驻资源在栈底);再到气闸:不等分的一大一小两块内存,玩家在狭小、无法回头的气闸区域里时卸载旧区域、加载新区域(《光环》《杰克 2》)。
- 粗粒度流送要求所有块大致等大;细粒度流送把所有资产切成等大的块,用块式池分配器按需加载卸载,避免碎片(《最后生还者》引擎)。
- Naughty Dog 用设计者放置的凸体关卡加载区域决定加载什么:取包围玩家的所有区域的块列表并集,与内存中的块比较后增删;区域的布置保证玩家看不到块消失,并有足够时间流送。
与本页对照:世界分区用网格单元和流送源的加载范围自动决定加载哪些单元格,不需要手工放置加载区域;"Block on Slow Streaming"选项对应 GEA 强调的"开始加载到可见之间要有足够时间"这一约束失败时的兜底(对比归纳)。PS4/PS5 的 PlayGo 边玩边下载,也以无缝流送为前提。
出处
- World Partition UE 5.8 文档
- World Partition - Data Layers UE 5.8 文档
- World Partition - HLOD UE 5.8 文档
- Game_Engine_Architecture_4th_Edtion_Volume_2_-_Jason_Gregory.pdf
- Jason Gregory《Game Engine Architecture》第 4 版(2026)卷 II 第 16 章 16.1.2、16.4.1 节
- Jason Gregory《Game Engine Architecture》第 4 版(2026)卷 II 第 17 章 17.4.1–17.4.3 节