Streaming an arbitrary sublevel by-name at runtime

Hi there, I want to know how to stream-in sublevels at runtime by-name, and append them under the current persistent level. As well as remove and unload those sublevels as I stream in new ones. I cannot have them manually added under the persistent level in the Editor – I will not know the names of the levels I’ll be streaming until runtime. The levels might not even exist in the base game and be mod content added later.

In the past I have created a working level-streaming system where levels (and their sublevels) are streamed-in by name, but I’ve always had to force the engine to travel to a new persistent level. It does it instantly when the levels are already streamed-in, but nevertheless the travel still takes place, causing the game mode to restart and a new pawn to be possessed.

This time, my goal is to never change my persistent level, never travel, never restart the gamemode, and just stream-in new sublevels that get appended to the persistent level.

Any information is appreciated, thank you.

1 Like

Take a look at ‘load level instance’ :slight_smile:

You can also load them async with a bit of effort

1 Like

Thanks Clockwork, this led me to my solution and I want to tag on some additional information!

What I ended up doing is making a modified version of ULevelStreamingDynamic::LoadLevelInstance (and LoadLevelInstance_Internal). The way it was implemented by Epic was somewhat limiting, but the bones of the streaming level system give us what we need.

I do the following:

  • Find the level by name or soft object pointer
  • Add it as a ULevelStreamingDynamic to the world
  • Bind to the ULevelStreamingDynamic’s OnLevelLoaded, OnLevelUnloaded, OnLevelShown, OnLevelHidden delegates.
  • Asynchronously load it in a similar way to UGameplayStatics::LoadStreamLevel, but do NOT activate it automatically
  • Once it’s done loading, activate the level by calling SetShouldBeVisible(true) on the ULevelStreamingDynamic.

(Unlike your solution where you call AsyncLoadAsset before-hand, I do the async loading using the streaming level system. I don’t know if this is better, but it felt more appropriate to use given that Epic put in this plumbing for level streaming.)

Breaking it out into steps is important is because various parts of the game need to hook into each step of the level transition process.

By the way: activating the level is the real slow part you need to hide. I learned this after implementing this. Basically, streaming the level from disk is pretty smooth, but it still takes a second or two (or more!) to activate the loaded level, and you’ll see its objects pop in rapidly over the time. It also seems even more prone to hitching than the streaming step. Be wary of this when designing your games!

Hopefully this is helpful for others with the same question.

1 Like

Great, sounds like it works well!

You’re right here, I think :slight_smile:

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.