Seamless, Proper Loading Screens! [Play Movies, Audio & Animated Widgets!]

Just got the Nick’s plug-in to work, I am soooo happy, now I can pass testing for the console!!! Yeaaaaaaaa THANK YOU NICK!!!

For everybody trying to get seamless travel to work with loading screen, it IS possible, I’ve figured it out, without too much additional modifications to TheJamsh’s code.

you’ll first need to make the functions callable from blueprint:


UCLASS()
class MYPROJECT_API UMyGameInstance : public UGameInstance
{
    GENERATED_BODY()

    public:
    virtual void Init() override;

    UFUNCTION(BlueprintCallable, Category = "Loading")
        virtual void BeginLoadingScreen(const FString& MapName);
    UFUNCTION(BlueprintCallable, Category = "Loading")
        virtual void EndLoadingScreen(UWorld* InLoadedWorld);

};


Then, use these exact settings if you want your loading screen to work automatically for both seamless and non-seamless travel. The key component is LoadingScreen.bAllowEngineTick = true; This allows the game thread to continue running while playing a movie, imitating the behavior of a non-seamless loadscreen call.


void UMyGameInstance::BeginLoadingScreen(const FString& InMapName)
{
    if (!IsRunningDedicatedServer())
    {
        FLoadingScreenAttributes LoadingScreen;
        LoadingScreen.WidgetLoadingScreen = FLoadingScreenAttributes::NewTestLoadingScreenWidget();

        LoadingScreen.bAutoCompleteWhenLoadingCompletes = true;
        LoadingScreen.MinimumLoadingScreenDisplayTime = 6000;
        LoadingScreen.bMoviesAreSkippable = false;
        LoadingScreen.bWaitForManualStop = false;
        LoadingScreen.bAllowEngineTick = true;

        GetMoviePlayer()->SetupLoadingScreen(LoadingScreen);
        GetMoviePlayer()->PlayMovie();
    }
}

void UMyGameInstance::EndLoadingScreen(UWorld* InLoadedWorld)
{
    GetMoviePlayer()->StopMovie();
}

Then inside blueprints (I’m using my Lobby’s pawn, that works for me), call your functions as such:

side note: I dont think Begin Loading Screen “Map Name” variable needs a value since it’s not used.

This will show the loading screen on all clients and listen server until your final map has finished loading. :slight_smile:

Is there some reason the plugin version doesn’t have the references to Widgets? Also – does it not work in PIE / VR Preview? It only seems to do anything for me if I play standalone…

Thank you TheJamsh for this tutorial!

I tried making a UMG work on the loading screen. First I call CreateWidget before setting the WidgetLoadingScreen and set it using the TakeWidget() function and somehow crashes package build. and Ideas why it does this?

Thank you so much.

Would it be possible to update it to 4.24.3 engine version? I’ve tried using it in a project on this version of the engine and it crashes.

Thank you very much.
I have a question: Where do I add the Bounses section, in the .h or .cpp of my custom gameinstance? ( I’m guessing .h)
+
the bounses section gives a lot of error when I copy and past it in the .h file Using 4.24

You don’t need to paste it anywhere, he’s just showing you what the “FLoadingScreenAttributes” struct contains. You already have access to the struct members as long as you included the MoviePlayer module.

So if you wanted to make movies unskippable, for example, you could use your FLoadingScreenAttributes object (which is called “LoadingScreen” in his example) and say “LoadingScreen.bMoviesAreSkippable = false”. Or if you wanted to change the MinimumLoadingScreenDisplayTime to 5 seconds, you could say “LoadingScreen.MinimumLoadingScreenDisplayTime = 5.0f”.

I’m doing something much like this, but I use a blueprint User Widget instead of a movie player.
I do this by using a multicast delegate that I bind to in a blueprint subclass of the custom C++ game instance class.
I also use the “sync streaming world load” function to make sure the world composition level is loaded before the player begins playing, so they don’t fall through the terrain.
I know that the right functions are called and that the widget is being created, because I PrintString() and it shows up, but the loading screen is all black, at least when using “play standalone.”
It’s as if either, there is a default black loading screen that goes in front of the widget I add, OR the widget doesn’t actually get drawn/refreshed before the world-load-sync happens and thus it never paints to the screen.

Has anyone seen this? Any suggestions? The way it goes is:

C++ GameInstance:
Create two multicast delegates for pre-load and post-load notifications.
In Init() -> Bind:
FCoreUObjectDelegates::PreLoadMap.AddUObject(this, &UScapesGameInstance::BeginLoadingScreen);
FCoreUObjectDelegates::PostLoadMapWithWorld.AddUObject(this, &UScapesGameInstance::EndLoadingScreen);
BeginLoadingScreen, EndLoadingScreen functions:
If not in dedicated server, call the loading screen delegates.

Blueprint GameInstance:
Init() -> bind pre-load, and post-load delegates to events
Pre-load bound event: create user widget instance, add to player screen (or to viewport, same outcome), print log message
Post-load bound event: remove the user widget instance, print log message

I see the log messages, and in the file, they’re a few seconds apart, so I don’t think it’s “being created after the blocking level load.”
So how do I get this to render as soon as it’s added?

Links to the wiki are broken, Epic recently moved the community wiki url to a new one. Links are all now sent to the landing page for UE forums

2 Likes

A bit late, but here is the link if anyone needed it:

3 Likes