Level Instances are how Unreal handles streaming of levels during gameplay. For level instances to work, they have to be set in the Persistent Level and tie them to streaming volumes or other loading mechanisms, but this instances are static.
Dynamic Level Instances are a way to spawn any level in any transform you want, and to actually be able to spawn multiple instances of the same level at the same time.
Let’s see how to do this.
Loading a Level Instance in Blueprint
To use them in Blueprint we can call the Load Level Instance function. There are two variants of this function, one takes an asset reference, the other loads a level simply by name ( useful if you have naming conventions and you want to load things via string concatenation like LVL_ … Factory … Left … 05 )
Any of this function takes a Location and Rotation argument in world-space that will place the level at a certain Transform.
After calling this function you will get a variable of type ULevelStreamingDynamic which represents a singular instance of that level in some coordinates in space.
You should store that variable as it will allow you to work with the level.
For instance, if we wanted the level to be loaded, but not visible, we could manipulate some of it’s properties to do so:
We can also register to when the level will actually finish loading, as this will use Unreal streaming capabilities to not hitch the game thread, but this means that it may take some time to load ( you can load synchronously if you want with some extra params by using C++ )
So usually what you will do is call the Load Level Instance node, and then add a binding to wait for when the level has been shown, and once that happens you can start querying the actors in your level, or do whatever you wanted with them.
Using Dynamic Level Instances in C++
Of course, all of this can also be done using C++, here are the same functions:
As you see, we get some extra functions, like the actual one that every other function calls with only FLoadLevelInstanceParams as a parameter.
This struct contains the same parameters we need, and allows you to modify things before they get loaded. ( Remember that this uses the Streaming System of Unreal, so it will be effective on the next Tick of the World )
As you see, the streaming functions by default set the bInitiallyLoaded to true, so that way you don’t need to set it initially, only if you don’t want to be true by default.
By the way, if you want an example of Dynamic Level Instance loading in action, the Pocket Worlds plugin uses them to spawn the levels it uses, here is a snippet of that:
Dynamic Level Instances as Procedural Map Pieces
Now that we know how to load dynamic levels any place in our world, we can use this for our procedural generator.
A way to use this is to think as each level as a Room or a Piece that we want to use.
We will need to of course provide some extra metadata of how this pieces can connect, via a data asset or maybe on the level assets asset manager tags themselves.
Once we have that, we can start constructing our procedural levels by combining such pieces one after the other.
A good benefit of working like this is that you can create the initial layout of the levels and then you can start to art your levels however you want using your usual Unreal tools that you would use to create any other level.
I think that if I’m not mistaken Returnal uses Level Instances as well to create it’s procedural world.
And that is all, now you now how you can also use Dynamic Level Instances to make Procedural Levels or for whatever other need you have.