Preface

When using Unreal Engine to design products, you often use map switching. Have you ever encountered a black screen for half a day when starting the software, or a black screen when switching maps? Customers always say that the experience is not good! Is there a way to solve it?

First, you need to understand why the screen is black. In fact, it is very simple! Because the computer needs to load disk assets after starting the software, the loading process takes time, but sometimes there are many assets to load, and the disk reading efficiency is low, so the waiting time is too long. During loading, the software window is idle, but there is no other rendering task, so the screen is black.

So most software will design a Loading page. The loading page actually loads small assets first (small number, fast speed), and then lets the form render the waiting page. For users, it will be much better to see the software feedback experience. Like general software startup display logo, advertisement, switch map display prompt information.

There are roughly two ways to implement loading pages in Unreal Engine

  • Pure waiting page, such as PlayerUnknown's Battlegrounds, add a waiting icon, and keep waiting in circles

  • Loading progress bar waiting page, with a progress bar to intuitively see the loading progress The difference between the two is that the first one does not know how long to wait, because it does not know the progress of executing background tasks. The second one can know the progress of executing background tasks, and the loading is completed when the progress is completed.

For the first one, we can find the implementation plan in the community wiki (need to be implemented in C++) Portal.

In this article, we mainly explain the second implementation plan.

Description

The first and second solutions are actually the same. Both require the use of background assets to load without hindering the logic execution of the foreground. The only difference is that the second solution has more information about the loading progress.

We need to use two functions (global functions) for the whole process

  • LoadPackageAsync: Complete asynchronous loading in the background

  • GetAsyncLoadPercentage: Get the completion progress of the loading process (value 0-100) There are clear comments in the source code to explain the design intention of the function

Suggestions

Generally, if you need to make a map progress bar, it is recommended to release the current level first to prevent the system from killing it due to excessive memory usage. **So the more common practice is generally to switch to a small level (openlevel) first. The official also uses this solution when implementing seamless switching. **

You can create a small level first, enable asynchronous background loading in the small level, and then open the target level after loading (since the level resources have been loaded, there is no need to wait to open the map)

Implementation

1. Start asynchronous loading of the map (execute the logic once, do not execute it multiple times), refer to the following:

c++
1
2
3
4
5
6
7
8
//MapPath is the map package name, the second parameter is to set an anonymous function to obtain the loading result, you can also design a binding callback function
LoadPackageAsync(MapPath.GetLongPackageName(), FLoadPackageAsyncDelegate::CreateLambda([this]( const FName& /*PackageName*/, UPackage* /*LoadedPackage*/, EAsyncLoadingResult::Type Result/*Result*/)
{
if (Result == EAsyncLoadingResult::Succeeded)
{
//Executable notification to switch maps, i.e. openlevel
}
}));

This code snippet can be written in the execution logic of starting the map switching, and it can be executed once.

Map package path: Right-click the map asset, copy the reference, and get the reference path. Remove the extra information and refer to the following:

Copy result: World’/Game/Environment_Set/Maps/Environment_Set_Map.Environment_Set_Map’

Package name:/Game/Environment_Set/Maps/Environment_Set_Map

Notification agent: The notification agent can set an anonymous function or bind to a member function. For details, please refer to the Unreal Unicast design. It is mainly used to notify the loading result.

**Pay attention to the parameter capture and incoming capture method in the anonymous function. Otherwise, the external notification cannot be completed. **

2. Get the asset loading progress.

c++
1
2
3
4
5
6
//Reference code, note that the return value range is 0-100, -1 means no loading package found
float ALoadActor::GetLoadPercent()
{
//Parameter passes in the package name of the loaded map, note that the parameter type is FName
return GetAsyncLoadPercentage(FName(MapPath.GetLongPackageName()));
}

Note that the progress should be polled, otherwise it is impossible to know the process after getting it once, after all, loading is a time-consuming process.

Finally

The whole process actually needs to be designed, and the core function is given above.

For your convenience, I wrote a plug-in, you can modify your project with the plug-in project.

During use, you need to call the subsystem API in the plug-in to complete the map switching. When switching, you need to provide the switching transition map and progress UI. Please refer to the project case for details.

Test packaging can be used, test platform Windows x64

Other versions of the engine can be directly upgraded.

Github: Project address

Unreal Engine: 4.27.2