Agent skill

Ue World Level Streaming

by quodsoler in quodsoler/unreal-engine-skills

A skill your agent uses when streaming levels in and out, setting up World Partition, or moving between maps.

MITAuto-check passedDatabases

Install Ue World Level Streaming

skills CLI
$ npx skills add quodsoler/unreal-engine-skills --skill ue-world-level-streaming -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install quodsoler/unreal-engine-skills ue-world-level-streaming --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/quodsoler/unreal-engine-skills.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/ue-world-level-streaming .claude/skills/ue-world-level-streaming && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
ue-world-level-streaming
GitHub stars
362
Token cost
~8k tokens
SKILL.md length
2,236 words
Files
2 (incl. references)
Skills in repo
31
Repo updated
First seen
Licence
MIT

At a glance

A skill your agent uses when streaming levels in and out, setting up World Partition, or moving between maps.

  • Works in 3 steps: Set bUseSeamlessTravel = true in the… → Set a transition map. Without one the… → Override the persistence hooks.…
  • Streaming levels in and out
  • SKILL.md covers Context, Choosing a Streaming Model, World Partition Runtime and Data Layers, plus 9 more sections
  • Instructions only: no scripts, shell commands, URLs or credentials in SKILL.md

What it does

Ue World Level Streaming is an agent skill from quodsoler/unreal-engine-skills. Use when streaming levels in and out, setting up World Partition, or moving between maps. Also use when the user mentions 'level streaming', 'World Partition', 'data layer', 'UDataLayerManager', 'SetDataLayerRuntimeState', 'LoadStreamLevel', 'UnloadStreamLevel', 'ULevelStreamingDynamic', 'LoadLevelInstance', 'ALevelInstance', 'streaming source', 'streaming volume', 'HLOD', 'OpenLevel', 'ServerTravel', 'seamless travel', 'sub-level', 'open world', or 'UWorldSubsystem'. For replication and net relevancy, see…

Its SKILL.md is about 8k tokens, which your agent loads only when the skill is triggered. The skill folder holds 2 other files, including reference files (for example `references/streaming-patterns.md`).

It sits in Databases, covering Database administration. The repository describes itself as: Unreal Engine C++ skills for AI coding agents. 27 skills covering gameplay, rendering, networking, animation, and more. Works with Claude Code, Cursor, Windsurf, and any agent… The licence is MIT.

When your agent uses it

  • Streaming levels in and out
  • Setting up World Partition
  • Moving between maps
  • The user mentions level streaming

Example prompts

  • “level streaming”
  • “World Partition”
  • “data layer”
  • “/ue-world-level-streaming”

Workflow steps

3 steps, taken from the first numbered list in SKILL.md.

  1. Set bUseSeamlessTravel = true in the GameMode constructor. It is already a UPROPERTY on AGameModeBase (GameModeBase.h:579) — do not…
  2. Set a transition map. Without one the engine transitions through an empty dummy world (World.cpp:8367). In PIE, seamless travel falls back…
  3. Override the persistence hooks. Signatures are verbatim from GameFramework/GameModeBase.h:239-268

What it can do on your machine

Read from SKILL.md and the folder at commit f3742d7. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    No scripts in the folder and no shell commands in SKILL.md (its code samples are cpp and ini).

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Ue World Level Streaming loads about 8k tokens when it runs, and up to ~13k if it reads all its reference files. Until then it costs about 171 tokens; SKILL.md has 2,236 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~171
When it runs · the whole SKILL.md, loaded when a task matches
~8k
With references · SKILL.md plus every file in references/, read only if the agent opens them
~13k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from quodsoler/unreal-engine-skills at commit f3742d7, republished under its MIT licence (© quodsoler). 2,236 words, ~7,982 tokens.

Download SKILL.mdSave it as .claude/skills/ue-world-level-streaming/SKILL.md (or your agent's skills folder). This skill also uses 1 other file; get the full folder from GitHub.
name
ue-world-level-streaming
description
Use when streaming levels in and out, setting up World Partition, or moving between maps. Also use when the user mentions 'level streaming', 'World Partition', 'data layer', 'UDataLayerManager', 'SetDataLayerRuntimeState', 'LoadStreamLevel', 'UnloadStreamLevel', 'ULevelStreamingDynamic', 'LoadLevelInstance', 'ALevelInstance', 'streaming source', 'streaming volume', 'HLOD', 'OpenLevel', 'ServerTravel', 'seamless travel', 'sub-level', 'open world', or 'UWorldSubsystem'. For replication and net relevancy, see ue-networking-replication; for GameMode travel callbacks, see ue-gameplay-framework; for saving world state to disk, see ue-serialization-savegames.
metadata.version
2.0.0
metadata.engine
5.8

UE World & Level Streaming

Target engine: UE 5.8. APIs below are verified against the 5.8 headers; older forms are listed under "Deprecated — do not use".

This skill covers how a UWorld is composed and swapped at runtime: World Partition grids, data layers, HLOD, level instances, classic sub-level streaming, streaming volumes, and map travel. Everything here lives in the Engine module (Engine/Source/Runtime/Engine), so Core, CoreUObject and Engine in PublicDependencyModuleNames is all that is needed. The one exception is the Level Streaming Persistence plugin, which adds the LevelStreamingPersistence module.

For end-to-end configurations per game type (open world, hub-and-spoke, procedural, chapter-based, volume-driven, dedicated server), see streaming patterns.

Context

Read .agents/ue-project-context.md if it exists (module names, conventions, enabled plugins, GAS/networking setup). Do not stop if it is missing.

Identify the area from the request and the codebase. Ask only when two plausible readings would produce different code.

Request is about…Go to
Picking between World Partition and sub-levelsChoosing a Streaming Model
Grid streaming, streaming sources, blocking loads, CVarsWorld Partition Runtime
Turning content on and off inside a partitioned worldData Layers
Reusable level chunks placed in the editor, packed actorsLevel Instances
LoadStreamLevel, ULevelStreaming, volumes, runtime instancingSub-Level Streaming
OpenLevel, ServerTravel, ClientTravel, seamless travelLevel Travel
Distant proxies for streamed-out cellsHLOD
Keeping actor changes across a streaming cycleLevel Streaming Persistence
Per-world managers, state that must survive travelWorld Subsystems and Cross-Level State

Choosing a Streaming Model

SituationUseWhy
One large continuous mapWorld Partition gridAutomatic spatial cells, no manual sub-level bookkeeping
Optional content inside a partitioned mapData layersEDataLayerRuntimeState toggles without travel
The same level asset placed many times in the editorALevelInstance / APackedLevelActorEdited as a unit, packed into instanced meshes
The same level package spawned many times at runtimeULevelStreamingDynamic::LoadLevelInstanceCreates a uniquely named package per instance
Discrete hand-authored zones in a non-partitioned mapULevelStreaming sub-levelsExplicit load and visibility control per zone
Proximity-driven interiors in a non-partitioned mapALevelStreamingVolumeCamera-position driven, no gameplay code
A different map entirelyOpenLevel / ServerTravelTears down and rebuilds the world

World Partition and sub-level streaming are mutually exclusive on the same persistent level. UWorld::IsPartitionedWorld() (Engine/World.h:2968) reports which one is in play; AWorldSettings::GetWorldPartition() (GameFramework/WorldSettings.h:837) returns the partition object (the WorldPartition member is protected).

World Partition Runtime

UWorldPartition (WorldPartition/WorldPartition.h) owns the runtime hash that turns actors into cells. UWorldPartitionSubsystem is the per-world entry point and is a UTickableWorldSubsystem.

cpp
#include "WorldPartition/WorldPartition.h"
#include "WorldPartition/WorldPartitionSubsystem.h"

UWorldPartitionSubsystem* Subsystem = GetWorld()->GetSubsystem<UWorldPartitionSubsystem>();
if (Subsystem && Subsystem->IsAllStreamingCompleted())
{
    // Every cell has finished loading, adding to or removing from the world.
}

Subsystem->ForEachWorldPartition([](UWorldPartition* Partition)
{
    return Partition->IsStreamingEnabled(); // return false to stop iterating
});

UWorldPartitionRuntimeCell is the unit the hash produces. Query readiness at an arbitrary point with a query source instead of polling actors:

cpp
#include "WorldPartition/WorldPartitionRuntimeCell.h"
#include "WorldPartition/WorldPartitionStreamingSource.h"

TArray<FWorldPartitionStreamingQuerySource> QuerySources;
QuerySources.Emplace(TargetLocation); // FVector

const bool bReady = Subsystem->IsStreamingCompleted(
    EWorldPartitionRuntimeCellState::Activated, QuerySources, /*bExactState=*/false);

EWorldPartitionRuntimeCellState is Unloaded, Loaded, Activated (WorldPartitionRuntimeCell.h:202).

Streaming sources

Any object can drive streaming by implementing IWorldPartitionStreamingSourceProvider (a plain interface struct in WorldPartitionStreamingSource.h) and registering it with the subsystem. For the common "this actor pulls cells in" case, add a UWorldPartitionStreamingSourceComponent instead — it already implements the provider and registers itself.

The two virtuals to override are virtual bool GetStreamingSources(TArray<FWorldPartitionStreamingSource>& StreamingSources) const and virtual const UObject* GetStreamingSourceOwner() const. Register in BeginPlay with UWorldPartitionSubsystem::RegisterStreamingSourceProvider(this) and release in EndPlay with UnregisterStreamingSourceProvider(this). A complete actor implementation is in streaming patterns.

  • EStreamingSourceTargetState: Loaded (in memory, not added to the world) or Activated.
  • EStreamingSourcePriority: Highest, High, Normal, Low, Lowest, Default (equals Normal).
  • TargetGrids plus EStreamingSourceTargetBehavior (Include / Exclude) restrict a source to named runtime grids.
  • bBlockOnSlowLoading opts the source into the engine's blocking path when streaming falls behind. Leave it false for cosmetic sources.
  • UWorldPartitionSubsystem::GetStreamingSources(const UWorldPartition*, TArray<FWorldPartitionStreamingSource>&) reads back everything currently registered.
Runtime CVars
CVarEffect
wp.Runtime.EnableServerStreamingServer-side cell streaming on dedicated and listen servers
wp.Runtime.EnableServerStreamingOutLets the server stream cells back out
wp.Runtime.BlockOnSlowStreamingBlocks the game thread when a blocking source falls behind
wp.Runtime.MaxLoadingStreamingCellsCaps concurrent cell loads
wp.Runtime.OverrideRuntimeLoadingRangeOverrides a grid's loading range for testing
wp.Runtime.ToggleDrawRuntimeHash2DDraws the cell grid on screen
wp.Runtime.DumpStreamingSourcesLogs every registered streaming source
wp.Runtime.HLODEnables and disables HLOD proxies at runtime

Data Layers

Actors reference data layers through AActor::DataLayerAssets (TArray<TSoftObjectPtr<UDataLayerAsset>>, GameFramework/Actor.h:1123). UDataLayerAsset is the authored asset, UDataLayerInstance is its per-world instance, and UDataLayerManager is the runtime accessor, reachable from any object inside a partitioned world.

cpp
// MyDataLayerController.h
#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MyDataLayerController.generated.h"

class UDataLayerAsset;

UCLASS()
class MYGAME_API AMyDataLayerController : public AActor
{
    GENERATED_BODY()

public:
    UFUNCTION(BlueprintCallable, Category = "MyGame|Streaming")
    void SetDungeonActive(bool bActive);

    UFUNCTION(BlueprintCallable, Category = "MyGame|Streaming")
    bool IsDungeonActivated() const;

protected:
    UPROPERTY(EditAnywhere, Category = "MyGame|Streaming")
    TObjectPtr<const UDataLayerAsset> DungeonLayer;
};
cpp
// MyDataLayerController.cpp
#include "MyDataLayerController.h"
#include "WorldPartition/DataLayer/DataLayerAsset.h"
#include "WorldPartition/DataLayer/DataLayerInstance.h"
#include "WorldPartition/DataLayer/DataLayerManager.h"

void AMyDataLayerController::SetDungeonActive(bool bActive)
{
    UDataLayerManager* Manager = UDataLayerManager::GetDataLayerManager(this);
    if (!Manager || !DungeonLayer)
    {
        return;
    }

    const EDataLayerRuntimeState NewState =
        bActive ? EDataLayerRuntimeState::Activated : EDataLayerRuntimeState::Unloaded;

    Manager->SetDataLayerRuntimeState(DungeonLayer, NewState, /*bInIsRecursive=*/true);
}

bool AMyDataLayerController::IsDungeonActivated() const
{
    UDataLayerManager* Manager = UDataLayerManager::GetDataLayerManager(this);
    if (!Manager || !DungeonLayer)
    {
        return false;
    }

    const UDataLayerInstance* Instance = Manager->GetDataLayerInstanceFromAsset(DungeonLayer);
    return Instance && Manager->GetDataLayerInstanceRuntimeState(Instance) == EDataLayerRuntimeState::Activated;
}

EDataLayerRuntimeState (DataLayerInstance.h:23): Unloaded, Loaded (in memory but not visible — use it to pre-warm), Activated (loaded and visible).

Other manager entry points: SetDataLayerInstanceRuntimeState(const UDataLayerInstance*, EDataLayerRuntimeState, bool bInIsRecursive), GetDataLayerInstanceEffectiveRuntimeState, GetDataLayerInstances(), GetDataLayerInstanceFromName(const FName&), and the BlueprintAssignable delegate OnDataLayerInstanceRuntimeStateChanged. To sweep every instance:

cpp
Manager->ForEachDataLayerInstance([](UDataLayerInstance* Instance)
{
    return Instance->IsRuntime(); // return false to stop early
});

Authority: a runtime data layer with no load filter only responds to state changes made on the server, and the resulting state replicates. Client-only layers must be changed on the client, server-only layers on the server. The old world-subsystem accessor still exists as a deprecated shim — see Deprecated — do not use; route everything through UDataLayerManager.

Level Instances

ALevelInstance (LevelInstance/LevelInstanceActor.h) places a .umap as a reusable chunk and implements ILevelInstanceInterface. ULevelInstanceSubsystem is the UWorldSubsystem that tracks them.

cpp
#include "Engine/World.h"
#include "LevelInstance/LevelInstanceActor.h"
#include "LevelInstance/LevelInstanceSubsystem.h"

void AMyLevelInstanceDriver::ShowRoom(ALevelInstance* RoomInstance)
{
    if (!RoomInstance)
    {
        return;
    }

    RoomInstance->LoadLevelInstance(); // queued; loads on the subsystem's next streaming update, so IsLoaded() is false this frame

    ULevelInstanceSubsystem* Subsystem = GetWorld()->GetSubsystem<ULevelInstanceSubsystem>();
    if (Subsystem && Subsystem->IsLoaded(RoomInstance))
    {
        Subsystem->ForEachActorInLevelInstance(RoomInstance, [](AActor* LevelActor)
        {
            LevelActor->SetActorTickEnabled(true);
            return true;
        });
    }
}
  • ILevelInstanceInterface runtime members: LoadLevelInstance(), UnloadLevelInstance(), IsLoaded(), GetLoadedLevel(), GetLevelStreaming(), GetWorldAsset(), GetLevelInstanceID(), IsInitiallyVisible().
  • ULevelInstanceSubsystem runtime members: GetLevelInstance(const FLevelInstanceID&), GetOwningLevelInstance(const ULevel*), RequestLoadLevelInstance(ILevelInstanceInterface*, bool bUpdate), RequestUnloadLevelInstance(ILevelInstanceInterface*), IsLoaded, IsLoading, ForEachActorInLevelInstance, GetLevelInstanceLevel. The editing entry points are WITH_EDITOR only.
  • ELevelInstanceRuntimeBehavior (LevelInstanceTypes.h:56) picks how the instance reaches the runtime: Partitioned (actors move into the main partition grid; shown as "Embedded") or LevelStreaming (its own streaming level; shown as "Standalone").
  • APackedLevelActor (PackedLevelActor/PackedLevelActor.h) derives from ALevelInstance and bakes its static meshes into instanced-mesh components. It reports ELevelInstanceRuntimeBehavior::None and loads no level at runtime.

Sub-Level Streaming

ULevelStreaming state

ELevelStreamingState (Engine/LevelStreaming.h:110) is Removed, Unloaded, FailedToLoad, Loading, LoadedNotVisible, MakingVisible, LoadedVisible, MakingInvisible. Read it with GetLevelStreamingState(). The requested side is ELevelStreamingTargetState (Unloaded, UnloadedAndRemoved, LoadedNotVisible, LoadedVisible).

cpp
#include "Engine/LevelStreaming.h"
#include "Kismet/GameplayStatics.h"

ULevelStreaming* Streaming = UGameplayStatics::GetStreamingLevel(this, FName("/Game/Levels/L_Zone_A"));
if (Streaming)
{
    Streaming->SetShouldBeLoaded(true);
    Streaming->SetShouldBeVisible(true);

    const bool bReady = Streaming->IsLevelLoaded() && Streaming->IsLevelVisible();
    ULevel* Loaded = Streaming->GetLoadedLevel();
}

Four BlueprintAssignable delegates, all with no parameters: OnLevelLoaded, OnLevelUnloaded, OnLevelShown, OnLevelHidden. Bind with AddDynamic to a no-argument UFUNCTION().

Use SetIsRequestingUnloadAndRemoval(true) to drop the streaming level object entirely. Never mutate UWorld::StreamingLevels directly — use AddStreamingLevel, AddStreamingLevels, RemoveStreamingLevel, RemoveStreamingLevels and UpdateStreamingLevelShouldBeConsidered (Engine/World.h:1073-1109), which maintain StreamingLevelsToConsider.

Latent load and unload

UGameplayStatics::LoadStreamLevel(const UObject* WorldContextObject, FName LevelName, bool bMakeVisibleAfterLoad, bool bShouldBlockOnLoad, FLatentActionInfo LatentInfo) and UnloadStreamLevel(const UObject* WorldContextObject, FName LevelName, FLatentActionInfo LatentInfo, bool bShouldBlockOnUnload) resume through FLatentActionInfo::ExecutionFunction, which is resolved by name through the reflection system. The callback therefore has to be a UFUNCTION() declared inside a class body in a header.

cpp
// MyStreamingActor.h
#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MyStreamingActor.generated.h"

UCLASS()
class MYGAME_API AMyStreamingActor : public AActor
{
    GENERATED_BODY()

public:
    void StreamInRoom(FName LevelName);
    void StreamOutRoom(FName LevelName);

    // UFUNCTION on the declaration is mandatory: FLatentActionInfo::ExecutionFunction
    // is looked up by name on CallbackTarget's UClass.
    UFUNCTION()
    void OnRoomLoaded();

    UFUNCTION()
    void OnRoomUnloaded();

protected:
    bool bRoomReady = false;
};
cpp
// MyStreamingActor.cpp
#include "MyStreamingActor.h"
#include "Engine/LatentActionManager.h"
#include "Kismet/GameplayStatics.h"

void AMyStreamingActor::StreamInRoom(FName LevelName)
{
    FLatentActionInfo LatentInfo;
    LatentInfo.CallbackTarget = this;
    LatentInfo.ExecutionFunction = FName("OnRoomLoaded");
    LatentInfo.Linkage = 0;
    LatentInfo.UUID = 1; // unique per pending latent action on this object

    UGameplayStatics::LoadStreamLevel(this, LevelName,
        /*bMakeVisibleAfterLoad=*/true, /*bShouldBlockOnLoad=*/false, LatentInfo);
}

void AMyStreamingActor::StreamOutRoom(FName LevelName)
{
    FLatentActionInfo LatentInfo;
    LatentInfo.CallbackTarget = this;
    LatentInfo.ExecutionFunction = FName("OnRoomUnloaded");
    LatentInfo.Linkage = 0;
    LatentInfo.UUID = 2;

    UGameplayStatics::UnloadStreamLevel(this, LevelName, LatentInfo, /*bShouldBlockOnUnload=*/false);
}

void AMyStreamingActor::OnRoomLoaded()
{
    bRoomReady = true;
}

void AMyStreamingActor::OnRoomUnloaded()
{
    bRoomReady = false;
}

LoadStreamLevelBySoftObjectPtr and UnloadStreamLevelBySoftObjectPtr take a TSoftObjectPtr<UWorld> in place of the FName and are the packaging-safe form. UGameplayStatics::FlushLevelStreaming(const UObject*) blocks until pending work completes; UWorld::FlushLevelStreaming(EFlushLevelStreamingType) gives finer control (None, Full, Visibility).

Runtime level instancing

ULevelStreamingDynamic loads one package repeatedly at different transforms. Prefer the params-struct overload, because the by-name overload cannot express a full FTransform.

cpp
#include "Engine/LevelStreamingDynamic.h"
#include "Engine/World.h"

ULevelStreamingDynamic* AMyDungeonGenerator::SpawnRoom(const FTransform& RoomTransform, const FString& InstanceName)
{
    ULevelStreamingDynamic::FLoadLevelInstanceParams Params(
        GetWorld(), TEXT("/Game/Levels/L_Room_Corridor"), RoomTransform);

    Params.OptionalLevelNameOverride = &InstanceName; // identical on server and clients
    Params.bInitiallyVisible = true;

    bool bSuccess = false;
    ULevelStreamingDynamic* Level = ULevelStreamingDynamic::LoadLevelInstance(Params, bSuccess);
    return bSuccess ? Level : nullptr;
}

Tear an instance down with SetShouldBeVisible(false), SetShouldBeLoaded(false), then SetIsRequestingUnloadAndRemoval(true). A generator that tracks its instances and binds OnLevelShown is in streaming patterns.

FLoadLevelInstanceParams members: World, LongPackageName, LevelTransform, OptionalLevelNameOverride (const FString*), OptionalLevelStreamingClass, bLoadAsTempPackage, bInitiallyVisible, bAllowReuseExitingLevelStreaming, EditorPathOwner, LevelStreamingCreatedCallback.

The Blueprint-exposed overloads are LoadLevelInstance(UObject* WorldContextObject, FString LevelName, FVector Location, FRotator Rotation, bool& bOutSuccess, const FString& OptionalLevelNameOverride, TSubclassOf<ULevelStreamingDynamic> OptionalLevelStreamingClass, bool bLoadAsTempPackage) and LoadLevelInstanceBySoftObjectPtr, which takes a TSoftObjectPtr<UWorld> in place of LevelName and the same tail parameters; a C++-only BySoftObjectPtr overload takes an FTransform (Engine/LevelStreamingDynamic.h:94).

Streaming volumes

ALevelStreamingVolume drives sub-levels from camera position. EStreamingVolumeUsage values: SVB_Loading, SVB_LoadingAndVisibility, SVB_VisibilityBlockingOnLoad, SVB_BlockingOnLoad, SVB_LoadingNotVisible. Set StreamingUsage on the volume; StreamingLevelNames lists what it affects and a streaming level's EditorStreamingVolumes array is the editor-side link. Set ULevelStreaming::bDisableDistanceStreaming = true to take a level off volume control, and MinTimeBetweenVolumeUnloadRequests to damp flicker at volume boundaries. Streaming volumes do nothing in a partitioned world.

Level Travel

CallHeaderEffect
UGameplayStatics::OpenLevel(const UObject*, FName LevelName, bool bAbsolute, FString Options)Kismet/GameplayStatics.h:340Tears down the world; clients disconnect
UGameplayStatics::OpenLevelBySoftObjectPtr(const UObject*, TSoftObjectPtr<UWorld>, bool, FString)Kismet/GameplayStatics.h:350Same, packaging-safe reference
UWorld::ServerTravel(const FString& InURL, bool bAbsolute, bool bShouldSkipGameNotify)Engine/World.h:4231Server moves, clients follow
APlayerController::ClientTravel(const FString& URL, ETravelType, bool bSeamless, FGuid)GameFramework/PlayerController.h:1413Client-initiated; TRAVEL_Absolute, TRAVEL_Partial, TRAVEL_Relative
UWorld::SeamlessTravel(const FString& InURL, bool bAbsolute)Engine/World.h:4243Background transition, connections kept
UGameplayStatics::GetCurrentLevelName(const UObject*, bool bRemovePrefixString)Kismet/GameplayStatics.h:358Current map name
Seamless travel
  1. Set bUseSeamlessTravel = true in the GameMode constructor. It is already a UPROPERTY on AGameModeBase (GameModeBase.h:579) — do not redeclare it.
  2. Set a transition map. Without one the engine transitions through an empty dummy world (World.cpp:8367). In PIE, seamless travel falls back to hard travel unless net.AllowPIESeamlessTravel=1 (GameModeBase.cpp:506).
ini
[/Script/EngineSettings.GameMapsSettings]
TransitionMap=/Game/Maps/L_Transition.L_Transition
  1. Override the persistence hooks. Signatures are verbatim from GameFramework/GameModeBase.h:239-268:
cpp
// MyGameMode.cpp
void AMyGameMode::GetSeamlessTravelActorList(bool bToTransition, TArray<AActor*>& ActorList)
{
    Super::GetSeamlessTravelActorList(bToTransition, ActorList);

    if (MyPersistentManager)
    {
        ActorList.Add(MyPersistentManager); // called for both legs (to transition, then to destination); add on both
    }
}

void AMyGameMode::PostSeamlessTravel()
{
    Super::PostSeamlessTravel();
}

void AMyGameMode::HandleSeamlessTravelPlayer(AController*& C)
{
    Super::HandleSeamlessTravelPlayer(C);
}

APlayerController::GetSeamlessTravelActorList(bool bToEntry, TArray<AActor*>& ActorList) is the client-side counterpart. APlayerController::SeamlessTravelTo(APlayerController* NewPC) / SeamlessTravelFrom(APlayerController* OldPC) and APlayerState::SeamlessTravelTo(APlayerState* NewPlayerState) copy per-player state onto the new objects. UWorld::IsInSeamlessTravel() and UWorld::SetSeamlessTravelMidpointPause(bool bNowPaused) control the midpoint; UWorld::OnSeamlessTravelStart and UWorld::OnSeamlessTravelTransition are static multicast delegates for observers.

Replication behaviour across travel (channel teardown, actor re-creation, net relevancy) belongs to ue-networking-replication; UNetDriver::NotifyActorLevelUnloaded(AActor*) is the hook it uses when a streamed level goes away.

Show full SKILL.md (862 more words)Show less

HLOD

HLOD produces stand-in proxies for cells that are streamed out. UHLODLayer (WorldPartition/HLOD/HLODLayer.h) configures a tier; grid placement comes from the runtime partition's settings rather than the layer. Hash and rebuild bookkeeping runs through UHLODRebuildPolicy and UHLODRebuildPolicyData, and builder settings (UHLODBuilderSettings) implement ComputeHLODHash(FHLODHashBuilder&).

At runtime, UWorldPartitionHLODRuntimeSubsystem (a UWorldSubsystem) tracks proxies as IWorldPartitionHLODObject, not as actors: RegisterHLODObject, UnregisterHLODObject, GetHLODObjectsForCell(const UWorldPartitionRuntimeCell*), OnHLODObjectRegisteredEvent(), OnHLODObjectUnregisteredEvent(), IsHLODEnabled(), IsWarmupEnabled(). AWorldPartitionHLOD and AWorldPartitionCustomHLOD (WorldPartition/HLOD/CustomHLODActor.h) both implement that interface, and AWorldPartitionHLODSourceCellPlaceholder stands in for a source cell during builds.

Build HLODs before shipping. Without them, everything past the loading range is simply absent.

Level Streaming Persistence

The Level Streaming Persistence plugin (Experimental in 5.8) keeps property values, destroyed-actor records and respawn data attached to streaming levels, so a level that streams out and back in returns changed. Add the LevelStreamingPersistence module to Build.cs.

ULevelStreamingPersistenceManager is a UWorldSubsystem. Blueprint-callable: SerializeTo(TArray<uint8>& OutPayload, bool bForceUpdate), InitializeFrom(const TArray<uint8>& InPayload), EjectPlacedActor(AActor*), RecreateActorInLevel(AActor*, ULevel* NewOwningLevel), RecreateActorInPersistentLevel(AActor*). Templated accessors SetPropertyValue, TrySetPropertyValue and GetPropertyValue read and write individual persisted properties by object path and property name. Which properties persist is declared in ULevelStreamingPersistenceSettings, a UDeveloperSettings with config Engine.

Call InitializeFrom once per map and early — from a custom UWorldSubsystem::Initialize — so values land before actors begin play. The payload it produces is what a USaveGame stores; see ue-serialization-savegames.

World Subsystems and Cross-Level State

UWorldSubsystem (Subsystems/WorldSubsystem.h) is created once per UWorld and dies with it, including on travel — the right home for a streaming manager or zone tracker. The full subsystem type table lives in ue-cpp-foundations.

Overridable hooks, verbatim from Subsystems/WorldSubsystem.h:34-66: virtual bool ShouldCreateSubsystem(UObject* Outer) const, virtual void PostInitialize(), virtual void OnWorldBeginPlay(UWorld& InWorld), virtual void OnWorldEndPlay(UWorld& InWorld), virtual void OnWorldComponentsUpdated(UWorld& World), virtual void PreDeinitialize(), virtual bool DoesSupportWorldType(const EWorldType::Type WorldType) const. Reach it with GetWorld()->GetSubsystem<UMyStreamingManager>(). A worked zone-manager subsystem is in streaming patterns.

For per-frame work derive from UTickableWorldSubsystem and implement Tick(float DeltaTime) plus GetStatId() const (pure virtual). Its Initialize and Deinitialize overrides are what arm and disarm ticking, so always call Super:: in both.

MechanismLifetimeUse for
UGameInstanceWhole application sessionCross-map player and session data
UGameInstanceSubsystemWhole application sessionServices that outlive every world
Seamless travel actor listTransition onlyActors that physically cross
UWorldSubsystemOne worldWorld-scoped caches; push to UGameInstance before travel
USaveGameDiskProgression — see ue-serialization-savegames

Deprecated — do not use

Do not emitUse in 5.8Source
AActor::DataLayers, FActorDataLayerAActor::DataLayerAssetsUE_DEPRECATED(5.8) in GameFramework/Actor.h:1115
UDataLayerSubsystemUDataLayerManagerUE_DEPRECATED(5.3) in WorldPartition/DataLayer/DataLayerSubsystem.h:37
AWorldDataLayers::OverwriteDataLayerRuntimeStatesUDataLayerManager::SetDataLayerRuntimeStateUE_DEPRECATED(5.8) in WorldPartition/DataLayer/WorldDataLayers.h:135
UDataLayerInstance::GetDataLayerFNameUObject::GetFNameUE_DEPRECATED(5.8) in WorldPartition/DataLayer/DataLayerInstance.h:190
UDataLayerManager::GetDataLayerInstanceNames outside the editorPass asset or instance pointers at runtimeUE_DEPRECATED(5.8) in WorldPartition/DataLayer/DataLayerManager.h:121
ULevelStreaming::ECurrentState, GetCurrentState()ELevelStreamingState, GetLevelStreamingState()UE_DEPRECATED(5.2) in Engine/LevelStreaming.h:367
UWorldPartitionLevelStreamingDynamic::LoadInEditor / UnloadFromEditorNo supported replacementUE_DEPRECATED(5.7) in WorldPartition/WorldPartitionLevelStreamingDynamic.h:63
UHLODBuilderSettings::GetCRC()ComputeHLODHash(FHLODHashBuilder&)UE_DEPRECATED(5.7) in WorldPartition/HLOD/HLODBuilder.h:43
UWorldPartitionHLODSourceActors::GetHLODHash()ComputeHLODHash(FHLODHashBuilder&)UE_DEPRECATED(5.7) in WorldPartition/HLOD/HLODSourceActors.h:27
AWorldPartitionHLOD::GetHLODHash / ComputeHLODHash / SetHLODHashGetHLODRebuildPolicyDataSet / SetHLODRebuildPolicyDataSet with UHLODRebuildPolicyDataUE_DEPRECATED(5.8) in WorldPartition/HLOD/HLODActor.h:146
UHLODLayer::GetCellSize / GetLoadingRange / IsSpatiallyLoadedRuntime partition settingsUE_DEPRECATED(5.7) in WorldPartition/HLOD/HLODLayer.h:82
UWorldPartitionHLODRuntimeSubsystem::RegisterHLODActor / GetHLODActorsForCell / GetNumOutdatedHLODActorsRegisterHLODObject / GetHLODObjectsForCell / GetNumOutdatedHLODObjectsUE_DEPRECATED(5.6) in WorldPartition/HLOD/HLODRuntimeSubsystem.h:77
AWorldPartitionCustomHLODPlaceholderAWorldPartitionHLODSourceCellPlaceholderUE_DEPRECATED(5.8) in WorldPartition/HLOD/CustomHLODPlaceholderActor.h:9
UWorldPartitionStreamingSourceComponent::TargetGrid / TargetHLODLayersTargetGrids with TargetBehaviorDeprecatedProperty in Components/WorldPartitionStreamingSourceComponent.h:63

Common Mistakes

UFUNCTION() above an out-of-line definition. A latent callback written as UFUNCTION() void AMyActor::OnRoomLoaded() {} in a .cpp is invisible to UHT, so FLatentActionInfo::ExecutionFunction never resolves and the continuation silently never fires. Declare it inside the class body in the header.

Reusing one FLatentActionInfo::UUID. Two pending actions on the same CallbackTarget that share a UUID collide and one is dropped. Give each call site its own constant.

Blocking loads outside a loading screen. bShouldBlockOnLoad = true, FlushLevelStreaming and wp.Runtime.BlockOnSlowStreaming all stall the game thread. On a server they stall every client.

Setting data-layer state on the client. A runtime data layer with no load filter only responds on the server; the state then replicates. Client-side calls appear to do nothing.

Mismatched dynamic level names in multiplayer. ULevelStreamingDynamic::LoadLevelInstance generates a unique package name per process. Without OptionalLevelNameOverride set to the same string on server and clients, the instances are different packages and nothing lines up.

Hard references across level boundaries. Unloading marks every object in the level package as garbage (LevelStreamingGCHelper.cpp:201-208), so a UPROPERTY() pointer from a persistent actor into a streamed level is nulled (a non-UPROPERTY raw pointer dangles) and does not re-point when the level streams back in. Use TSoftObjectPtr or TWeakObjectPtr across boundaries.

Expecting streaming volumes to work in World Partition. They do not. Use data layers or a streaming source instead.

Assuming the dedicated server streams like a client. Server cell streaming is off unless enabled, and its sources are the ones you register. Check UWorldPartition::IsServerStreamingEnabled() before debugging "missing" actors on the server.

Mutating UWorld::StreamingLevels directly. It bypasses StreamingLevelsToConsider, so the level is never evaluated. Use the AddStreamingLevel / RemoveStreamingLevel family.

Skipping Super::Initialize / Super::Deinitialize in a UTickableWorldSubsystem. Those calls are what enable and disable ticking.

  • ue-cpp-foundations — the full subsystem type table, TObjectPtr, TSoftObjectPtr, GC and object lifetime rules.
  • ue-networking-replication — replication across travel, net relevancy, DOREPLIFETIME, dedicated-server authority.
  • ue-gameplay-framework — GameMode and GameState travel callbacks, login flow, UGameInstance role.
  • ue-data-assets-tables — UDataAsset (the base of UDataLayerAsset), async asset loading, Asset Manager.
  • ue-procedural-generation — PCG-driven content that populates partitioned levels.
  • ue-serialization-savegames — USaveGame, writing the Level Streaming Persistence payload to disk.
  • ue-actor-component-architecture — component design for streaming-source actors and world managers.
  • ue-game-features — Game Feature plugins, GameFeatureAction and the modular component manager
  • ue-sequencer-cinematics — Level Sequences, playback, cine cameras and Movie Render Graph

© quodsoler, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

SKILL.md and 1 other file (references) in skills/ue-world-level-streaming of quodsoler/unreal-engine-skills.

  • SKILL.md
  • references/streaming-patterns.md

Open the folder on GitHubat commit f3742d7

Compare with similar skills

Ue World Level Streaming next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Ue World Level Streaming compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Ue World Level Streaming this skillquodsoler/unreal-engine-skills362—~8kAutomated safety check: PassMIT
Hybrid Cloud Outboxesgetsentry/sentry46k—~4.8kAutomated safety check: PassCustom licence
Replicate Video AdJingyi-Wu-Richael/replicate-video-ad1081 repos~1.6kAutomated safety check: PassNone
Sea Orm 2FlyinPancake/yoink112—~2.9kAutomated safety check: PassApache-2.0
Pixel Perfect ReplicationYu-369/VibeCurb979—~8.7kAutomated safety check: PassMIT
Horse Database PoolingHashLoad/horse1.4k—~1.4kAutomated safety check: PassMIT

Similar skills

  • Hybrid Cloud Outboxes

    getsentry/sentry

    Official

    Guide for creating and maintaining outbox-based eventually consistent operations in Sentry.

    46k GitHub stars~4.8k tokensUpdated today
    DatabasesAuto-check passed
  • Replicate Video Ad

    Jingyi-Wu-Richael/replicate-video-ad

    Analyze a reference video frame by frame and turn its visual grammar, story beats, dialogue, product reveal, proof sequence, and conversion structure into a production-ready ecommerce story-ad…

    108 GitHub starsUsed in 1 repo~1.6k tokens
    DatabasesAuto-check passed
  • Sea Orm 2

    FlyinPancake/yoink

    Expert guidance for SeaORM 2.0, Rust's async ORM with strongly-typed columns, nested ActiveModels, Entity Loader API, and entity-first workflow.

    112 GitHub stars~2.9k tokensUpdated 5 days ago
    DatabasesAuto-check passed
  • Image-to-code replication pipeline. An agent skill from Yu-369/VibeCurb.

    979 GitHub stars~8.7k tokensUpdated 2 mo ago
    DatabasesAuto-check passed
  • Guide for setting up thread-safe database connection pooling (FireDAC / UniDAC) in multithreaded Horse applications.

    1.4k GitHub stars~1.4k tokensUpdated 3 days ago
    DatabasesAuto-check passed
  • Redis Clustering

    redis/agent-skills

    Official

    Redis Cluster and replication guidance covering hash tags for multi-key operations, avoiding CROSSSLOT errors, and reading from replicas to scale read-heavy workloads.

    166 GitHub starsUsed in 1 repo~1k tokens
    DatabasesAuto-check passed

More from quodsoler/unreal-engine-skills

All 31 skills in this repo
  • Unreal Actor-Component Architecture

    quodsoler/unreal-engine-skills

    Unreal Engine C++ guidance for AActor and UActorComponent: lifecycle hooks, spawning, component creation and attachment, ticking, interfaces and composition.

    362 GitHub stars~7.5k tokensUpdated 11 days ago
    Auto-check passed
  • Unreal Engine AI and Navigation

    quodsoler/unreal-engine-skills

    Guides Unreal Engine C++ AI work across AI controllers, behavior trees, blackboards, perception, navmesh pathfinding, EQS and Smart Objects.

    362 GitHub stars~8.9k tokensUpdated 11 days ago
    Auto-check passed
  • Unreal Engine Animation System

    quodsoler/unreal-engine-skills

    Reference for writing and debugging Unreal Engine 5.8 animation C++: AnimInstance and proxy, montages, notifies, curves, blend spaces, state machines, linked layers and root motion.

    362 GitHub stars~7k tokensUpdated 11 days ago
    Auto-check passed
  • Unreal Engine Async and Threading

    quodsoler/unreal-engine-skills

    Picks and applies the right Unreal Engine C++ concurrency API, from UE::Tasks and FPipe to ParallelFor, FRunnable, locks and timers, with game-thread safety rules.

    362 GitHub stars~8k tokensUpdated 11 days ago
    Auto-check passed
  • Ue Audio System

    quodsoler/unreal-engine-skills

    A skill your agent uses when playing, mixing or debugging sound in Unreal Engine — one-shot SFX, looping ambience, music, dialogue or procedural audio.

    362 GitHub stars~7.9k tokensUpdated 11 days ago
    Auto-check passed
  • Unreal Blueprint and C++ Interop

    quodsoler/unreal-engine-skills

    Reference for exposing Unreal Engine C++ to Blueprint and calling Blueprint from C++, covering UFUNCTION and UPROPERTY specifiers, latent and async nodes, and interfaces.

    362 GitHub stars~7.8k tokensUpdated 11 days ago
    Auto-check passed

Categories

Questions about Ue World Level Streaming

What does Ue World Level Streaming do?

A skill your agent uses when streaming levels in and out, setting up World Partition, or moving between maps. Ue World Level Streaming is an agent skill from quodsoler/unreal-engine-skills. Use when streaming levels in and out, setting up World Partition, or moving between maps.

When should I use Ue World Level Streaming?

Ue World Level Streaming fits situations like: streaming levels in and out; setting up World Partition; moving between maps; the user mentions level streaming.

How do I install Ue World Level Streaming in Claude Code?

Run `npx skills add quodsoler/unreal-engine-skills --skill ue-world-level-streaming -a claude-code`. Or copy the skill folder (skills/ue-world-level-streaming in quodsoler/unreal-engine-skills) into .claude/skills/ue-world-level-streaming in your project. Claude Code loads it when a task matches its description.

How do I install Ue World Level Streaming in Codex?

Run `npx skills add quodsoler/unreal-engine-skills --skill ue-world-level-streaming -a codex`. Or copy the skill folder (skills/ue-world-level-streaming in quodsoler/unreal-engine-skills) into .agents/skills/ue-world-level-streaming in your project. Codex loads it when a task matches its description.

Can I use Ue World Level Streaming in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add quodsoler/unreal-engine-skills --skill ue-world-level-streaming -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/ue-world-level-streaming, .gemini/skills/ue-world-level-streaming, .github/skills/ue-world-level-streaming and .opencode/skills/ue-world-level-streaming in your project.

What does Ue World Level Streaming need to run?

SKILL.md names no scripts, command-line tools or credentials: Ue World Level Streaming is instructions for the agent only.

Does Ue World Level Streaming access the network?

SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.

Is Ue World Level Streaming safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Ue World Level Streaming use?

Ue World Level Streaming is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Ue World Level Streaming use?

About 8k tokens (SKILL.md is roughly 32k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 4.9k tokens, read only when the agent opens those files.

What are the alternatives to Ue World Level Streaming?

Skills that share tags, products or a category with Ue World Level Streaming: Hybrid Cloud Outboxes (getsentry/sentry, 46k stars), Replicate Video Ad (Jingyi-Wu-Richael/replicate-video-ad, 108 stars), Sea Orm 2 (FlyinPancake/yoink, 112 stars) and Pixel Perfect Replication (Yu-369/VibeCurb, 979 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Ue World Level Streaming?

quodsoler (a GitHub user) maintains it in quodsoler/unreal-engine-skills, which has 362 GitHub stars. The repository holds 31 skills in this directory. The repository was last updated on September 28, 2026.

Source: quodsoler/unreal-engine-skills on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.