See Animating a Slate widget on how to create an animated slate widget.

Setting up the loading screen

Before you start loading the level, place the Slate widget into the viewport. This can be done for example in your GameInstance class.

//Note: you should store LoadingScreen as TSharedPtr<SMyLoadingScreen>
LoadingScreen = SNew(SMyLoadingScreen);
GEngine->GameViewport->AddViewportWidgetContent(LoadingScreen.ToSharedRef(), 99);

If you’ve set up the animation for the widget to start right away, doing this will trigger that also. Once the animation finishes, you can start the level loading process as normal. The widget will remain on screen for the duration of loading.

Removing the loading screen

If you don’t need the loading screen to animate out, you can simply remove it from the viewport when the level has finished loading:

//Bind this delegate *before* you start loading the level
PostLoadMapHandle = FCoreUObjectDelegates::PostLoadMapWithWorld.AddLambda([this](UWorld* World)
{
	FCoreUObjectDelegates::PostLoadMapWithWorld.Remove(PostLoadMapHandle);
 
	GEngine->GameViewport->RemoveViewportWidgetContent(LoadingScreen.ToSharedRef());
});

However, if you want to animate the loading screen, such as having it slide out or fade out, you need to bind to a few more delegates.

//Bind this delegate *before* you start loading the level
PostLoadMapHandle = FCoreUObjectDelegates::PostLoadMapWithWorld.AddLambda([this, LevelAsset](UWorld* World)
{
	FCoreUObjectDelegates::PostLoadMapWithWorld.Remove(PostLoadMapHandle);
 
	WorldPostActorTickHandle = FWorldDelegates::OnWorldPostActorTick.AddLambda([this](UWorld* World, ELevelTick TickType, float Delta)
	{
		FWorldDelegates::OnWorldPostActorTick.Remove(WorldPostActorTickHandle);
		
		GetWorld()->GetTimerManager().SetTimerForNextTick(FTimerDelegate::CreateLambda([this]()
		{
			//Replace this with whatever logic you need to run - such as
			//triggering the animation, and binding to the animation's delegate
			HideLoadingScreen();
		}));
	});
});

The reason for this is there appears to be some kind of a hitch or other issue that occurs during the level loading process, which causes the FCurveSequence animation to skip. The issue does not occur during Play in Editor, but happens in Standalone mode.

I’m not sure if there’s some other way to avoid it, but waiting for the first actor tick, and then waiting for the next tick via the timer appears to avoid the problem. If you know/find a better way, do let me know (find my contact info on the home page)