How to check if a Data Layer has been loaded.
I needed a way to check if a data layer was done loading so it would automatically open some doors when it was done loading. The Valley of the Ancient had an example of how to do it in blueprints using a Timer by Event which would construct a query and check specific data layers.
I took that and created a latent node version that checks if all partition streaming is complete as i didn't need to check specific data layers. I did this to keep the graph flow cleaner for our team.
I've included the code and also the blueprint example.
How Valley of the Ancient implements it in Blueprints (UE 5.7)
The two Blueprints you need to look at are BP_DarkWorldRift and BP_AncientGameMode.
DarkWorldRift has a function called SwapDataLayers and, the relevant bits,:
apply a custom high priority loading implemented in c++ (which might be needed for a big world but i don't)
binds to an OnTranistionComplete delegate on he GameMode
calls BeginDarkWorldTransition and passes the PlayerCharacter's location
OnTranistionComplete:
Applies default priority loading
Force Garbage Collection

In AncientGameMode, the BeginDarkWorldTransition function:
unloads the current data layer
flushes streaming
starts a 0.01 Timer by Event which calls ReadyToLoad

The ReadyToLoad function has the streaming complete check. It's a custom BP function.
Test Streaming
It takes a DataLayerActor which seems like the only way to get the FName of a data layer currently.
And the Query Source Location which is the PlayerCharacter that was passed.
Then afterwards it loads the DarkWorld and starts another 0.01 Timer by Event which calls CheckReadyToReveal which calls the same TestStreaming function and then calls the EventDispatcher

The TestStreamingState function:
gets all the ActorDataLayerNames from the params
Uses that to construct a query Source
uses the IsStreamingCompleted function that's part of the World Partition Subsystem

I made a Latent Action Node (UE 5.7)
It might be easier to read on the Unreal Community
WaitForAllStreamingCompletion.h
#pragma once
#include "WorldPartition/WorldPartitionHelpers.h"
#include "WorldPartition/WorldPartitionSubsystem.h"
class FWaitForAllStreamingCompletion : public FPendingLatentAction
{
public:
FName ExecutionFunction;
int32 OutputLink;
FWeakObjectPtr CallbackTarget;
UWorldPartitionSubsystem* WorldPartitionSubsystem;
FWaitForAllStreamingCompletion(const FLatentActionInfo& LatentInfo):
ExecutionFunction(LatentInfo.ExecutionFunction)
, OutputLink(LatentInfo.Linkage)
, CallbackTarget(LatentInfo.CallbackTarget)
{
if (UWorld* World = GEngine->GetWorldFromContextObjectChecked(CallbackTarget.Get()))
{
WorldPartitionSubsystem = World->GetSubsystem<UWorldPartitionSubsystem>();
}
}
virtual void UpdateOperation(FLatentResponse& Response) override
{
if (!WorldPartitionSubsystem)
{
Response.DoneIf(true);
}
Response.FinishAndTriggerIf(WorldPartitionSubsystem->IsAllStreamingCompleted(), ExecutionFunction, OutputLink, CallbackTarget);
}
};BlueprintFunctionLibrary .h
UFUNCTION(BlueprintCallable, Category="WorldPartition|DataLayers", meta=(Latent, WorldContext="WorldContextObject", LatentInfo="LatentInfo"))
static void WaitForAllStreamingCompletion(const UObject* WorldContextObject, struct FLatentActionInfo LatentInfo );BlueprintFunctionLibrary .cpp
void USystemLibrary::WaitForAllStreamingCompletion(const UObject* WorldContextObject, struct FLatentActionInfo LatentInfo)
{
if (UWorld* World = GEngine->GetWorldFromContextObject (WorldContextObject, EGetWorldErrorMode::LogAndReturnNull))
{
FLatentActionManager& LatentActionManager = World->GetLatentActionManager();
if (LatentActionManager.FindExistingAction <FWaitForAllStreamingCompletion>(LatentInfo.CallbackTarget, LatentInfo.UUID) == nullptr)
{ LatentActionManager.AddNewAction(LatentInfo.CallbackTarget, LatentInfo.UUID, new FWaitForAllStreamingCompletion(LatentInfo));
}
}
}
Comments