It is common to use "Open Level" when you load different levels in Unreal Engine.
But "Open Level" is a synchronous process, and it makes the game freeze while loading a level.
For this reason, it is common to load levels asynchronously while displaying a loading animation.
This article explains how to load a level asynchronously in the Unreal Engine while displaying the loading animation.
Loading a level using OpenLevel
First, we will show how to load another level without displaying a loading animation.
Generally, it is common to use "Open Level" when you load a level synchronously in Unreal Engine.
"Open Level" makes the game process (including the drawing process) stop until the specified level is loaded.
This makes the game freeze.
If the screen fades out gradually before "Open Level" is executed, the game looks much more natural.
But if it remains dark for a long time, the player is anxious whether the game is running correctly or frozen.
For this reason, loading another level asynchronously is a basic strategy while displaying loading animations or game tips.
Loading a level with a loading animation
Loading a new level asynchronously with a loading animation on the Unreal Engine requires tricky processes.
To realize the loading levels asynchronously, we will shows a demo that loads a level with a loading animation.
The flow of the demo of loading levels with a loading animation is as follows.
- At the beginning of the game (after pressing the Play button), the first Level (Level A) is loaded first.
- When the B button is pressed, the loading animation is displayed and the second Level (Level B) is loaded simultaneously.
- When Level B is loaded, "Level B Loaded" is displayed on the screen.
- When Level B is loaded, the loading animation and Level A are disappeared.
- When Level A is loaded, the loading animation is appeared.
- When Level A is loaded, "Level A Loaded" is displayed on the screen.
- When Level A is loaded, the loading animation and Level A are disappeared.
From here, we will explain how to realize this process.
To realize the asynchronous processing of levels, create a level loaded asynchronously and a level that manages the levels.
The management level loads the levels asynchronously.
In the Unreal Engine, a Persistent Level should be a management level, and a sub level should be loaded asynchronously by it.
Since a Persistent Level is a unique level in the game and can hold multiple sub levels, it is suitable to be used as a level to manage its sub levels.
- "Open Level" loads this Persistent Level. This indicates that the Persistent Level can only be read synchronously.
To realize the demonstration, we will consider the following level structure.
Create a level with the name displayed in the Level Name.
Note that the loading animation is also managed as the sub level by the Persistent Level in order to dynamically show/hide the loading animation without switching the Persistent Level.
|Sub Level (Level A)
|Sub Level (Level B)
|Sub Level (Loading Animation)
Once you create these levels, then realize the above level structure.
First, open the Level tab with the Level "L_LevelGroup" opened.
Add three sub levels and turn off the visibility of all then.
This makes these sub levels unloaded when the Persistent Level is loaded.
Level Loading Process
The process of loading sub levels (L_LevelA and L_LevelB) asynchronously while displaying the loading animation is as follows.
- Load L_LoadingAnimation asynchronously using "Load Stream Level (by Name)".
- Check "Make Visible After Load" in "Load Stream Level (by Name)" to display a loading animation after L_LoadingAnimation has loaded.
- Load the level (L_LevelA or L_LevelB) asynchronously using "Load Stream Level (by Name)".
- Check "Make Visible After Load" in "Load Stream Level (by Name)" to display the loaded level.
- Delete the old level (L_LevelB if L_LevelA is loaded) and L_LoadingAnimation using "Unload Stream Level (by Name)".
By displaying a loading animation in the process of loading L_LevelA and L_LevelB, it is possible to prevent the game to be frozen.
A similar method can be used to display game tips instead of the loading animation.
However, the old level will continue to exist while the new level is being loaded.
It should be careful for the old level’s process (Disable the player’s input if necessary) not to cause the bugs.
Implement the Level Loading Process
We will show the process of the implementation by Blueprint.
The implementation flow is as follows.
- Create UI (W_LoadingAnimation) for the loading animation.
- Create a Blueprint Interface (BP_LoadingInterface) for communication between L_LevelGroup and L_LoadingAnimation.
- Add loading process of the loadtion animation to the Blueprint of L_LevelGroup.
- Add loading process of L_LevelA or L_LevelB to the Blueprint of L_LoadingAnimation.
- Add a process to output a message after loading is completed to the Blueprint ofL_LevelA and L_LevelB.
- Delete old levels and loading animations.
To understand the overview, we will show the file structure for the demo as follows.
From here, we will explain each step will in detail.
1. Create UI for the Loading Animation
Create UI for the loading animation that will be displayed while the level is being loaded.
For this demo, we will create an asset called W_LoadingAnimation derived from the User Widget.
The W_LoadingAnimation displays the text "Now Loading …" at the centered, and adds an animation that blinks the text at one-second intervals.
Open the Blueprint editor and add a Play Animation node.
Then connects to the Event Construct.
Specify the animation you created and set "Num Loops to Play" to 0.
This makes the animation loop indefinitely.
2. Create a Blueprint Interface
L_LevelGroup switches the level to be loaded according to the input button.
For this purpose, we implement the common process in L_LoadingAnimation.
L_LevelGroup and L_LoadingAnimation are connected by Blueprint Interface.
The Blueprint Interface has an argument for passing the level name.
- We have another method to implement a common process as a function in L_LevelGroup. But this is not possible because the common process includes asynchronous processes. To solve this problem, we implement the common process in L_LoadingAnimation and call from L_LevelGroup via Blueprint Interface.
The asset name of the Blueprint Interface is "BP_LoadingInterface".
Add the function "LoadingAnimationLoaded" with two inputs.
|Level to load
3. Add Loading Process of Loading Animation
Add a process to load the loading animation.
In this demonstration, the loading animation is created as the sub level L_LoadingAnimation.
The sub level is loaded by "Load Stream Level (by Name)".
The argument Level Name is the name of the level to be loaded (In this case, L_LoadingAnimation).
As indicated by the clock symbol in the upper right corner of the node, "Load Stream Level (by Name)" is executed asynchronously.
When "Load Stream Level (by Name)" is executed, the loading of L_LoadingAnimation is complete.
When loading is completed, issue the message "Loading Animation Loaded" created in the Blueprint Interface to L_LoadingAnimation.
Specify L_LevelA to the input NextLevel when key A is pressed, and specify L_LevelB when key B is pressed.
Specify the current level to the input CurrentLevel.
When the game starts (when the BeginPlay event is issued), L_LevelA is loaded.
We connects to Begin Play node about the same process when key A is processed.
Next, implement the process executed for the event "Loading Animation Loaded" in L_LoadingAnimation.
UI of the loading animation W_LoadingAnimation, is displayed by using "Create Widget" and "Add to Viewport".
4. Add the Level Loading Process
After the loading animation is loaded, loads the level (L_LevelA or L_LevelB).
This is accomplished by "Load Stream Level (by Name)" in the same way as loading the loading animation.
The argument Level Name specifies the level to be loaded.
Here, we use the input Next Level of "Loading Animation Loaded".
The level loading can be a very time-consuming process depending on the amount of data contained in the level.
When you load a level with the almost initial state, the execution time is trivial.
It makes us difficult to see the effect of asynchronous loading.
Therefore, we will add a "Delay" node after the "Load Stream Level (by Name)".
This takes the loading process for more than 3 seconds at least.
5. Add a Process to Output a Message after Loading is Completed
After the loading process is completed, output a message to shows that the loading is complete.
In this demonstration, we implement by using "Remote Event".
The event names are as follows.
|L_LevelA has loaded
|L_LevelB has loaded
Next, open the Blueprint for L_LevelA.
Create a Custom Event "L_LevelALoaded.
Connect a "Print String" node to "L_LevelALoaded" to output the message "L_LevelA Loaded" when the event is received.
Similarly, create a custom event in Blueprint for L_LevelB.
6. Delete Old Levels and Loading Animations
Return to the Blueprint for L_LoadingAnimation.
After sending the event with "Remote Event", delete the old level and loading animation.
To delete the old level first, specify the input Current Level of "Loading Animation Loaded" to "Unload Stream Level (by Name)".
Once the level is deleted, delete the loading animation.
Use "Reomve from Parent" to delete the loading animation W_LoadingAnimation from L_LoadingAnimation.
Finally, specify L_LoadingAnimation to "Unload Stream Level (by Name)" to remove the loading animation.
Let’s try loading the level with the loading animation.
When the play button is pressed with L_LevelGroup opened, the loading animation "Now Loding …" is displayed for a while.
Then, "Now Loding …" is displayed and the loading animation disappears.
Pressing key B displays "Level B Loaded" after the loading animation appears.
In the same way, pressing key A displays "Level A Loaded" after the loading animation appears.
You will see that a loading animation is displayed while the level is loading.
- Because key input is not disabled during the loading, pressing a key during the loading may not work properly. It is necessary to disable key input during the loading process as you can see.
We have explained how to load a level with the loading animation.
Although the procedure for asynchronous level loading is complicated, it is worth to implement for the UI improvement.
The asynchronous level loading described in this article is also used for open world games.
Try to refer to this article when you implement the asynchronous leel loading in the Unreal Engine.