Most open-world performance problems aren't caused by bad art — they're caused by bad streaming. Developers coming from Unreal Engine 4 are used to manually placing Level Streaming Volumes and wrestling with persistent levels. World Partition, introduced in UE5, eliminates most of that busywork and replaces it with a spatial cell grid that loads and unloads actors automatically based on proximity and data layer rules. Get it wrong and your world hitches every time the player moves. Get it right and you can ship hundreds of square kilometres with a sub-200ms streaming budget.
What Is World Partition and Why It Replaces the Old Level Streaming Model
World Partition is a system built directly into the UE5 World Settings that divides your map into a configurable grid of cells. Each cell is an independent streaming unit. When the camera moves within a defined radius of a cell, UE5 begins async loading the actors in that cell; when the camera moves away, they're unloaded. This is fundamentally different from the UE4 approach where you manually set up sub-levels and streaming volumes.
The key advantages:
- Single persistent level — no more sub-level spaghetti. One map file, one Outliner, one source control history.
- Automatic partitioning — UE5 handles which actors land in which cells based on their world position at save time.
- Scalable distance — you can assign different streaming radii to different Runtime Grids, useful for separating environment geometry (wide radius) from interactive props (tight radius).
- Editor streaming — in the editor, you can load only a spatial region for iteration without loading the full world.
World Partition is enabled by default in new UE5 projects using the Open World template. For existing projects, go to World Settings → World Partition → Enable World Partition, then run the automated level conversion tool (Edit → Convert Level). The conversion splits your existing actors across cells automatically.
Setting Up World Partition in a New UE5 Project
![]()
Start from the Open World template in the UE5 project browser — it ships with World Partition pre-configured and a 4 km² Landscape ready for iteration. If you're starting from scratch:
- Open World Settings (Window → World Settings).
- Under World Partition, confirm Enable World Partition is checked.
- Set your Runtime Grid cell size. The default is 12800 Unreal Units (128 m). For dense urban environments with many small props, drop to 6400 UU. For sparse wilderness, 25600 UU is acceptable.
- Configure Loading Range — the distance from the player at which cells begin streaming. A value of 102400 UU (1024 m) covers most third-person games at a generous radius.
Verify in the World Partition Editor (Window → World Partition). You'll see your world divided into a colour-coded grid. Green cells are loaded in editor; grey are unloaded. Clicking any region loads it for editing without touching other cells.
```cpp
// Trigger a World Partition loading state change from C++ (e.g. for cinematics)
#include "WorldPartition/WorldPartitionRuntimeCell.h"
void AMyGameMode::ForceLoadRegion(FVector Center, float Radius)
{
UWorldPartitionSubsystem* WPSubsystem = GetWorld()->GetSubsystem<UWorldPartitionSubsystem>();
if (WPSubsystem)
{
FWorldPartitionStreamingQuerySource Query;
Query.Location = Center;
Query.Radius = Radius;
WPSubsystem->ForceStreamingSourceState(EStreamingSourceTargetState::Loaded, Query);
}
}
```
For Blueprint-driven cutscenes, use the Level Streaming Volume override node in Sequencer, or simply teleport the active `AWorldPartitionReplayController` pawn to pre-load cells before the camera cut arrives.
Organizing 3D Assets for World Partition: Cell Size, Runtime Grids, and Actor Layers
![]()
Your asset organisation strategy directly affects streaming performance. World Partition doesn't care about your Content Browser folder structure — it cares about where actors live in world space and which Runtime Grid they're assigned to.
Runtime Grids let you create multiple independent streaming grids with different cell sizes and loading radii:
| Grid Name | Cell Size (UU) | Loading Radius (UU) | Intended Content |
|---|---|---|---|
| MainGrid | 12800 | 102400 | Landscape, large static meshes, skybox actors |
| PropGrid | 6400 | 51200 | Interactive props, destructibles, pickups |
| NPCGrid | 3200 | 25600 | AI characters, spawn volumes |
Assign actors to a specific grid by selecting them in the Outliner → Details → World Partition → Runtime Grid. For most static environment geometry, the default MainGrid is correct. NPCs and gameplay objects should be on smaller grids so they stream tightly around the player.
Group related assets spatially. Scatter props randomly and your cell boundaries will constantly split logical groupings across two cells, causing both to stream simultaneously for a single visual cluster. Instead, treat each cell footprint as a design unit — dress a town square so that every prop for that square falls within one or two adjacent cells.
For assets sourced from the BitSoul marketplace, download your GLB or FBX assets, import them into UE5's Content Browser, then place them within a defined spatial grid zone. Static Mesh Actors placed in the viewport are automatically assigned to a cell at save time. Nanite-enabled meshes work seamlessly with World Partition since Nanite's virtualized geometry operates independently of the streaming system.
Data Layers for Dynamic Streaming: Day/Night, Interior/Exterior, and Quest States
Data Layers are World Partition's mechanism for toggling entire groups of actors at runtime — independent of spatial proximity. This is the right tool for:
- Day/Night variants — a daytime prop set (open market stalls, crowds) in one Data Layer; a nighttime set (closed shutters, fewer NPCs) in another.
- Interior vs Exterior — load detailed interior actors only when the player enters a building trigger, regardless of cell streaming state.
- Quest-gated content — a destroyed village variation visible only after a specific quest flag is set.
Create Data Layers in the Data Layers Outliner (Window → World Partition → Data Layers). Assign actors by selecting them → right-click → Assign to Data Layer. At runtime, toggle layers via Blueprint:
```blueprint
// Blueprint node: Set Data Layer Runtime State
// Target: World Partition Subsystem
// DataLayer: [your data layer asset reference]
// State: Loaded | Unloaded | Activated
```
Or from C++:
```cpp
UDataLayerSubsystem* DLSubsystem = GetWorld()->GetSubsystem<UDataLayerSubsystem>();
DLSubsystem->SetDataLayerRuntimeState(NightLayerAsset, EDataLayerRuntimeState::Activated);
```
Keep Data Layers orthogonal to Runtime Grid assignment. A Data Layer controls *whether* actors stream; the Runtime Grid controls *when* they stream based on distance. An actor can belong to both simultaneously.
Performance Budgeting and Debugging World Partition Streaming
UE5 ships with several tools for diagnosing World Partition streaming costs.
World Partition Streaming Performance Profiler — run `wp.Runtime.ShowRuntimeSpatialHashCells 1` in the console to visualize active cells overlaid on the viewport in different colours based on load state (loading, loaded, unloading).
Stat commands to watch:
```
stat WorldPartitionStreamingPerf
stat LevelStreaming
```
Target a per-frame streaming budget of under 2 ms on your minimum spec hardware. If you see spikes when the player crosses cell boundaries, your cell size is too small relative to actor count. Either increase cell size or reduce actor density.
World Partition HLOD (Hierarchical Level of Detail) — enable HLODs under World Settings → World Partition → HLOD Layer. UE5 automatically builds simplified mesh proxies for distant, unloaded cells, ensuring visual continuity. Run `HLODs.BuildHLODs` in the editor command line before shipping. HLOD actors appear in cells outside the loading radius, replacing the full-detail actors with a fraction of the draw calls.
For assets purchased on BitSoul marketplace, ensure that LODs are set up correctly before placement. An asset with only LOD0 and no LOD1/2 will contribute full-detail geometry to the HLOD proxy build, inflating the proxy triangle count. Use the LOD Generation tool in the Static Mesh Editor to generate at least two lower LODs before adding the asset to a World Partition level.
Shipping Checklist
Before you package an open-world UE5 project using World Partition:
- [ ] Runtime Grid cell sizes tuned per asset category (environment / props / NPCs)
- [ ] Loading Radius validated on minimum-spec hardware (no hitches on cell boundary crossing)
- [ ] Data Layers assigned for all quest-gated and time-of-day content
- [ ] HLOD layers built and validated in Standalone Play mode
- [ ] `wp.Runtime.ShowRuntimeSpatialHashCells 1` pass completed, no unexpected cell load spikes
- [ ] All Nanite meshes have Fallback mesh configured for non-Nanite hardware targets
- [ ] Collision meshes simplified (UCX_ prefix) to avoid streaming large collision geometry
- [ ] Content Browser cleaned: no orphaned actors outside the World Partition grid
World Partition removes the biggest source of level streaming complexity that plagued UE4 open-world projects. The spatial cell model, combined with Data Layers and HLOD proxies, gives you a production-grade streaming pipeline with minimal manual configuration. Get your Runtime Grids right early — retrofitting cell sizes after a level is fully dressed is painful.
Ready to populate your open world? Browse game-ready environment assets, modular props, and character meshes at BitSoul marketplace — all formatted for direct UE5 import.