2.9.16.0
Coherent GT for UE4
Building a Loading Screen

This tutorial will explain how to use GT to create a loading screen. The tutorial describes the workings of the LoadingScreen_Map level in the sample CoUIGTTestFPS game. The LoadingScreen_Map is almost a duplicate of the ComplexMenu_Map but the loading screen is separated into a separate HTML file and run as part of UE4's loading screen.

Requirements

Currently, the loading screen feature works only when GT is in asynchronous mode. To change the synchronicity mode, go to the GT plugin's settings (Coherent GT -> Options -> Run Asynchronous) Changes to the synchronicity require an engine restart.

Additionally, due to a limitation of UE4 (for which we've contacted Epic) GT cannot run as a loading screen before the first level. That is, you can use GT as a loading screen in between levels, but not before your first level has loaded.

The loading screen settings

The loading screen can be configured with the following options, all found in FCoherentUIGTLoadingScreenSettings:

  1. URL - containing the URL for the loading screen's view.
  2. Wait for manual stop flag - if true, waits the user to press any button to stop the loading screen.
  3. Auto complete when loading complete flag - if true, the loading screen will disappear as soon as the loading of the level is done.
  4. Minimum loading screen display time - the minimum time the loading screen should be opened for (in seconds), negative value if there is no minimum time.

Note: Not all options can be used simulteniously - Wait for manual stop flag and Minimum loading screen display time are conflicting.

Setup the loading screen

For UE4 versions post 4.11, the setup of the loading screen can be at any time before the level change, e.g. it can be in the BeginPlay's method of the Game's GameMode. For 4.10 and 4.11 you must make sure that the engine doesn't change resolution in the time between the loading screen is setup and the level is actually changed.

  • If you don't want to exchange information between C++ and JS during the loading screen, the setup is as simple as calling the SetupLoadingScreen Blueprint function.
BP_setup.png
Loading screen setup via BP
  • If you do want to exchange information, you must use C++ code (as Blueprints aren't evaluated while the level is being loaded), the setup is as follows:
    FCoherentUIGTLoadingScreenSettings LoadingScreenSettings;
    LoadingScreenSettings.URL = "coui://UIResources/loading_screen_sample/loading_screen.html";
    TSharedPtr<SCoherentUIGTLoadingScreenWidget> LoadingScreen = ICoherentUIGTPlugin::Get().SetupLoadingScreen(LoadingScreenSettings);
    
Warning
If GT is running in synchronous mode, ICoherentUIGTPlugin::SetupLoadingScreen will return nullptr.

Using timers

Since the engine's main loop is blocked while the level is loaded, your code needs to have another way to send continious updates to the UI. For this, you can use the SCoherentUIGTLoadingScreenWidget::RegisterLoadingScreenTimer method which let you hook up a callback to be called every now and then. For example, as seen in the sample code for CoUIGTTestFPSLoadingScreenGameMode.cpp:

FWidgetActiveTimerDelegate can be easily created via a lambda function, e.g:

// A function to update the progress in the UI using dummy values
FWidgetActiveTimerDelegate ProgressBarDelegate = FWidgetActiveTimerDelegate::CreateLambda([this](double /*InCurrentTime*/, float /*InDeltaTime*/)
{
    static float LoadingProgress = 0.f;
    LoadingScreen->GetView()->TriggerEvent("LoadingScreenProgress", LoadingProgress += 0.01f);
    return EActiveTimerReturnType::Continue;
});
// Hook up both functions to timers. The timers will be cleared automatically when the loading screen is finished.
LoadingScreen->RegisterLoadingScreenTimer(0.1f, ProgressBarDelegate);

Since it's invalid to use TriggerEvent before the the GT is ready to transfer data between C++ and JS, you'll find that that example code wait for GT to become ready before starting the timers:

void ACoUIGTTestFPSLoadingScreenGameMode::PrepareLoadingScreen()
{
    ...
    auto LoadingScreen = ICoherentUIGTPlugin::Get().SetupLoadingScreen(LoadingScreenSettings);
    auto Helper = new FLoadingScreenHelper(LoadingScreen); // Will self-delete when the loading screen is done
    // Wait for GT to be ready for C++ <-> JS communication before doing anything
    LoadingScreen->ViewListenerOwner.ReadyForBindings.AddRaw(Helper, &FLoadingScreenHelper::OnLoadingScreenReadyForBindings);
}
Note
Be careful when you are making copies of the slate widget's shared pointer as this may leak the loading screen resources. You don't have to worry about widget's timers and the ViewListenerOwner delegates - they are auto-cleared at the end of the loading screen.

HTML code

As mentioned, the LoadingScreen_Map closely resembles the ComplexMenu_Map. The HTML pages are almost identical except for some small difference which this paragraph will cover:

  1. Instead of having multiple screens inside one HTML page, the screens are split into separate HTML files.
  2. The splash screen at the beginning is removed
  3. Updates to the loading screen are sent from C++ by triggering events instead of Blueprints.