Skip to content

Load Stream Level / Unload Stream Level

At a glance

Lives in: Blueprint API / Game; implemented by Gameplay Statics - Returns: no loaded-level object in Blueprint; the latent Completed pin fires when the stream request finishes - Fails by: doing nothing useful, never showing the level you expected, or completing with an invalid setup you still need to debug - Official docs: Load Stream Level, Loading and Unloading Levels using Blueprints, Level Streaming Overview, and UGameplayStatics

The one-minute version

  • Load Stream Level requests a sublevel to be loaded into the current persistent world. It is a latent node: the graph continues from Completed later.
  • Make Visible After Load means "show the streamed level once it is loaded." Loaded and visible are separate states.
  • Unload Stream Level requests a streamed level to be removed from the world.
  • Calling load again while the same latent load is already pending does not stack a second useful load.
  • These nodes are not Open Level. Streaming keeps the persistent world alive; Open Level travels to another map and destroys the old world actors.
  • Level streaming does not save actor state for you, replicate a gameplay rule by itself, or make direct references to actors in unloaded sublevels safe.

What they actually do

Streaming works inside a persistent level:

flowchart LR
    P[Persistent Level] --> A[Always present actors]
    P --> S1[Streamed sublevel: L_Interior]
    P --> S2[Streamed sublevel: L_Basement]

Load Stream Level asks the world to load a named sublevel package and, if requested, make it visible. Unload Stream Level asks the world to hide/remove that streamed level.

pseudocode of the engine behavior - not engine source

function LoadStreamLevel(LevelName, MakeVisible, ShouldBlock, LatentInfo):
    StreamingLevel = find streaming level by package/name
    if StreamingLevel is None:
        finish latent action without a useful loaded level
        return

    if this load request is already pending:
        keep the existing request
        return

    StreamingLevel.ShouldBeLoaded = true
    StreamingLevel.ShouldBeVisible = MakeVisible
    wait until streaming update completes
    fire Completed

function UnloadStreamLevel(LevelName, ShouldBlockOnUnload, LatentInfo):
    StreamingLevel = find streaming level by package/name
    if StreamingLevel is None:
        finish without removing anything useful
        return

    StreamingLevel.ShouldBeLoaded = false
    StreamingLevel.ShouldBeVisible = false
    wait until streaming update completes
    fire Completed

For the bigger model, read Level streaming basics.

When it fails (and what failure does)

Failure often looks like "nothing changed" rather than a Blueprint error.

Common causes:

  1. The level name is wrong. Use the package/sublevel name Unreal expects, not a display label you invented in the graph.
  2. The level is not configured as a streamed sublevel. A normal map name for Open Level is not automatically available as a streaming level in the current persistent world.
  3. You loaded but did not make it visible. Loaded data can exist without being rendered or active the way a beginner expects.
  4. You already have the same request in flight. Repeated calls before the first finishes do not create a queue of duplicate loads.
  5. You kept direct references to actors that are not loaded anymore. Actors in unloaded sublevels can be destroyed or unavailable; use managers, IDs, soft references, or rebinding after load.
  6. Blocking flags caused a hitch. Blocking load/unload can stall play while the work is completed.
  7. Multiplayer state is underspecified. Streaming level visibility and gameplay authority are separate. Decide whether the server, each client, or local presentation owns the request.

There is no returned Level object to validate from the basic Blueprint node. Use prints, Get Streaming Level, PIE logs, and the Levels window to prove which level is loaded and visible.

The pattern everyone actually uses

For a doorway/interior:

Persistent-level trigger BeginOverlap
-> filter player
-> Load Stream Level("L_ShopInterior",
                     Make Visible After Load = true,
                     Should Block on Load = false)
-> Completed
-> enable shop interaction / fade out loading prompt

Trigger EndOverlap or exit event
-> Unload Stream Level("L_ShopInterior",
                       Should Block on Unload = false)

For a first project, keep the trigger/manager in the persistent level, not inside the sublevel that may unload itself.

The C++ twin, for the curious (our own example code):

void ALevelDoorway::RequestInteriorLoad()
{
    FLatentActionInfo LatentInfo;
    LatentInfo.CallbackTarget = this;
    LatentInfo.ExecutionFunction = FName("OnInteriorLoaded");
    LatentInfo.Linkage = 0;
    LatentInfo.UUID = 1;

    UGameplayStatics::LoadStreamLevel(
        this, FName("L_ShopInterior"), true, false, LatentInfo);
}

Streaming state is not save state

Loading a sublevel is a runtime visibility/memory choice. It does not mean:

  • actors in that sublevel keep custom state after being unloaded,
  • SaveGame data is written,
  • every client has made the same visibility choice,
  • old references from before unload are safe.

If a chest in a streamed room should stay opened, store a durable ID/value in a manager, GameInstance, replicated state, or SaveGame, then apply it when the level loads again.

Lookalikes - which one do I want?

Node / system Changes Use when
Load Stream Level Loads a sublevel into the current persistent world You want an area to appear without full map travel.
Unload Stream Level Removes a streamed sublevel You want to free/hide an area while keeping the persistent world.
Get Streaming Level Returns the streaming-level object, or None You need to inspect or change a streaming level directly.
Open Level Travels to another map/world You want a full map change and old world actors should be replaced.
Level Streaming Volumes Editor-driven stream triggers Loading should be driven by player location and volume setup.
World Partition Large-world streaming system You are building large spatial worlds beyond beginner sublevel setup.
SaveGame Disk-backed durable data State must survive quitting or relaunching.

Rule of thumb: Use streaming to keep the current world and swap pieces of it; use Open Level to leave the world; use SaveGame to keep data outside the world.

Going deeper