UE5 World Partition

发布时间:2026/7/7 8:04:19
UE5 World Partition 核心概念 1CellCell 就是地图格子。想象俯视图---------------- | A1 | A2 | A3 | A4 | ---------------- | B1 | B2 | B3 | B4 | ---------------- | C1 | C2 | C3 | C4 | ----------------每个格子里保存一批 Actor树 石头 房子 路牌 地形片段 小道具玩家在 B2 附近时可能加载A1 A2 A3 B1 B2 B3 C1 C2 C3离远的 A4、C4 就不加载。Cell和Grid是两个层级区别很重要。你可以这么理解Grid 切地图的规则 Cell 按这个规则切出来的格子就像棋盘规则 Grid 棋盘上的每一个小格子 Cell一个 Grid 里Cell 大小通常是一样的。比如MainGrid Cell Size 25600 Loading Range 76800那这个MainGrid切出来的所有 Cell 大小都是 25600。MainGrid: ------------ | C | C | C | ------------ | C | C | C | ------------ | C | C | C | ------------ 每个 C 都是 25600 大小所以我前面说“每个 Cell 一样”指的是同一个 Grid 里的 Cell 一样大。但 UE 可以有多个 Runtime Grid。比如SmallObjectGrid Cell Size 6400 Loading Range 20000 BuildingGrid Cell Size 25600 Loading Range 80000 LandscapeGrid Cell Size 51200 Loading Range 150000这时候就变成SmallObjectGrid切得很碎 BuildingGrid切得中等 LandscapeGrid切得更大也就是不同 Grid 的 Cell 大小可以不同。一个 Grid 切出一堆 Cell 另一个 Grid 也切出另一堆 Cell 它们可以覆盖同一片世界区域 但不是父子包含关系这种两个grid也会是存在的Actor 是否 Spatially LoadedActor 有个很重要的属性Is Spatially Loaded如果开启这个 Actor 根据它所在 Cell 来加载/卸载比如树、石头、房子。如果关闭它不跟随空间 Cell通常一直加载比如GameMode 相关管理器 天气系统 全局音频管理 任务系统 世界规则 Actor如果一个很远的普通 Actor 被设成 Always Loaded它永远占内存 大地图就慢慢爆比如天空盒核心概念 5Data LayerData Layer 是另一种维度的开关。它不是按距离加载而是按“状态/类别”加载。比如白天版本 夜晚版本 任务前版本 任务后版本 破坏前城市 破坏后城市 开发调试层例子DataLayer_City_Normal DataLayer_City_Destroyed任务前加载正常城市任务后切到破坏城市。所以World Partition 负责空间切分 Data Layer 负责状态切换相对于浣熊市核弹爆炸前加载正常城市核弹爆炸后卸载正常城市加载破坏后的城市室内 / 地下 / 多层空间会让 WP 不够聪明World Partition 本质是空间分块主要按世界坐标划分。但搜打撤常见结构是地上城市 地下室 下水道 楼内多层 地铁 堡垒它们在 XY 上可能重叠但玩法上完全不同。例如地面商场 地下停车场 地下实验室它们 XY 坐标接近Cell 可能一起被加载。这时你要考虑Data Layer 区分地下/地上Runtime Grid 是否分开室内是否用 Level Instance地下空间是否单独 Streaming SourceAI/Navmesh 是否分层管理否则会出现玩家在地面 地下大量 Actor 也被加载这个时候需要你手写辅助逻辑。Data Layer 自己不会判断“玩家在地上还是地下”。更准确地说Data Layer 开关 程序/蓝图 判断什么时候开关比如玩家进地下入口 Trigger ↓ 你的逻辑判断玩家要进地下 ↓ 把 DataLayer_Underground 设为 Loaded / Activated ↓ 必要时把部分地表表现卸掉核心概念 6HLODHLOD 是远景替身。如果玩家离一个城市很远不应该加载城市里每栋房子的真实 Actor。应该加载一个合并后的低成本模型远处城市 HLOD Mesh靠近后再换成真实房子、窗户、门、灯牌。简单说近处真实 Actor 远处HLOD 替身没有 HLOD 的大地图很容易变成远处看不清的东西还在按真实物体渲染非常亏。World Partition 的运行逻辑可以想成这样玩家移动 ↓ 更新 Streaming Source 位置 ↓ 计算哪些 Cell 在加载范围内 ↓ 加载新 Cell ↓ 卸载远离的 Cell ↓ 远处显示 HLOD ↓ 近处显示真实 Actor真正危险的地方有几个。第一个引用把远处资源拉进来。比如 B2 的一个 Blueprint 引用了 C9 的某个大资源B2 Cell 加载 ↓ Blueprint 引用远处资源 ↓ 远处资源也被加载这样 World Partition 就被你绕过了。硬引用会绕过 World Partition这是大地图项目经典坑。比如 B2 Cell 里的一个 Blueprint 硬引用了 C9 区域的大资源BP_QuestDevice Hard Reference - BP_BossRoom Hard Reference - 大贴图 / 大蓝图 / 大音效 / 大特效结果B2 Cell 加载 ↓ 硬引用资源一起加载 ↓ 远处资源被提前拉进内存World Partition 只能管 Actor 空间加载管不了你蓝图硬引用把资源拉进来。TA 要做引用规范大资源用 SoftObjectPtr / SoftClassPtr任务资源用 AssetManager 管UI 图标、音频、特效不要随便硬挂到地图 Actor定期跑 Reference Viewer / Size Map检查 Cell 加载时实际拉了哪些包第二个Actor 太碎。比如一片区域有几万个小 Actor石头 Actor 草 Actor 树枝 Actor 垃圾 ActorCell 切换时管理成本很高。玩家移动到新区域World Partition 要做加载 Cell 包 反序列化 Actor 创建 UObject 创建 Component RegisterComponent 创建 RenderState 加入 Scene 创建 PhysicsState 加入 Collision 更新 Bounds 加入 Octree / Scene 管理结构 可能执行 BeginPlay / Construction玩家离开区域时又要UnregisterComponent 释放 RenderState 移除 Collision EndPlay 标记销毁 等待 GC如果一个 Cell 里是 50 个 Actor还好。如果一个 Cell 里是 5000 个小 Actor就会卡这时候应该考虑Foliage Instance ISM / HISM 合并 Mesh HLOD第三个Cell 太小或太大都不行。Cell 太小加载/卸载太频繁 IO 请求碎 管理成本高Cell 太大一次加载太多东西 内存峰值高 切换卡顿先用经验值起步小物件 / 道具 Grid128m ~ 256m 建筑 / 中型场景 Grid256m ~ 512m 地形 / 大结构 Grid512m ~ 1km HLOD Grid1km ~ 2km 或更大所以我可以地形单独开一个grid不影响场景其他东西吗对可以。地形单独开一个 Grid 是合理的而且很常见。它不会天然影响其他场景物体因为Actor 属于哪个 Runtime Grid就按哪个 Grid 的规则流送World Partition 只管 Actor 加载不管“游戏状态”这是搜打撤最容易踩坑的地方。比如箱子被搜过门被打开电闸被拉下撤离点是否开放Boss 是否死亡某个房间是否已被玩家触发掉落物是否还在地上如果这些状态只存在 Actor 身上AChestActor::bHasBeenLooted true;那 Cell 卸载后 Actor 销毁再加载时很可能又回到默认状态。所以 World Partition 下搜打撤应该这样设计Cell Actor 负责表现、交互、碰撞、动画 服务器 MatchState / Manager 负责保存真实状态Actor 加载时Actor BeginPlay ↓ 用 StableID 找服务器状态 ↓ 恢复表现Actor 变化时玩家开门 / 搜箱 ↓ 服务器修改状态表 ↓ Actor 播动画 ↓ 同步给相关客户端二次元项目特别要小心 HLOD 破坏画风二次元开放世界很依赖描边色块分区材质 ID阴影分层法线风格化轮廓线稳定性角色/建筑的剪影但 World Partition 远处通常会切 HLOD。