#unreal#gotchas

In Play in Editor the Level Instance actor is loaded and shown immediately. In standalone or Packaged builds it isn’t, which can cause problems if you’re trying to access actors inside it.

The following code can be used to determine when the instance has been successfully shown.

if(LevelInstance->IsLoaded())
{
	//the instance is visible already
	return;
}
 
LevelInstance->LoadLevelInstance();
//LoadLevelInstance only queues up the load, and it won't happen until UpdateStreamingState
//gets called. This in turn is only called on tick, so we have to call it manually for this to work
LevelInstance->GetLevelInstanceSubsystem()->UpdateStreamingState();
ULevelStreaming* const* StreamingPtr = LevelInstance->GetWorld()->GetStreamingLevels().FindByPredicate([this](ULevelStreaming* LevelStreaming)
{
	//There are different kinds of level streaming classes, LevelInstanceSubsystem
	//uses ULevelStreamingLevelInstance
	if(const auto* InstanceStreaming = Cast<ULevelStreamingLevelInstance>(LevelStreaming))
	{
		return InstanceStreaming->GetLevelInstance() == LevelInstance;
	}
 
	return false;
});
 
if(StreamingPtr != nullptr)
{
	ULevelStreaming* Streaming = *StreamingPtr;
	//Unclear if this can happen, but added as a safety check
	if(Streaming->IsLevelLoaded())
	{
		HandleComplete();
		return;
	}
	//It seems that OnLevelLoaded doesn't get called in cases of ALevelInstance at least
	//so we have to use OnLevelShown to get anything to happen
	//Streaming->OnLevelLoaded.AddDynamic(this, &ThisClass::LevelLoaded);
	Streaming->OnLevelShown.AddDynamic(this, &ThisClass::LevelLoaded);
	return;
}
 
//This probably shouldn't happen if your level instance actor is valid
UE_LOGFMT(LogTemp, Error, "Cannot find LevelStreaming instance for level instance {level}", GetNameSafe(LevelInstance));