After a morning of struggling with this, I think I have a solution.
I make the solution in C++, this is the code:
void ACorridorActor::LoadLevel(const FName LevelName, const FTransform& LevelTransform)
{
auto CurrentLevel = UGameplayStatics::GetStreamingLevel(GetWorld(), LevelName);
if (CurrentLevel && !CurrentLevel->IsLevelLoaded())
{
LoadedLevelTransform = LevelTransform;
LoadedLevelName = LevelName;
FLatentActionInfo LatentInfo;
LatentInfo.Linkage = 0;
LatentInfo.UUID = 1;
LatentInfo.CallbackTarget = this;
LatentInfo.ExecutionFunction = "CallbackOnLevelLoaded";
UGameplayStatics::LoadStreamLevel(this, LevelName, false, false, LatentInfo);
}
else if (CurrentLevel == nullptr)
{
UE_LOG(LogTemp, Error, TEXT("ERROR: Could not load level %s, level not found!"), *LevelName.ToString());
}
}
void ACorridorActor::CallbackOnLevelLoaded()
{
auto CurrentLevel = UGameplayStatics::GetStreamingLevel(GetWorld(), LoadedLevelName);
if (CurrentLevel)
{
#if WITH_EDITOR
FLevelUtils::SetEditorTransform(CurrentLevel, LoadedLevelTransform);
#endif
CurrentLevel->LevelTransform = LoadedLevelTransform;
CurrentLevel->SetShouldBeVisible(true);
OnLevelLoaded.Broadcast();
}
}
void ACorridorActor::UnloadLevel(FName LevelName)
{
const auto CurrentLevel = UGameplayStatics::GetStreamingLevel(GetWorld(), LevelName);
if (CurrentLevel && CurrentLevel->IsLevelLoaded())
{
FLatentActionInfo LatentInfo;
LatentInfo.Linkage = 0;
LatentInfo.UUID = 0;
LatentInfo.CallbackTarget = this;
LatentInfo.ExecutionFunction = "CallbackOnLevelUnloaded";
UGameplayStatics::UnloadStreamLevel(this, LevelName, LatentInfo, false);
}
}
void ACorridorActor::CallbackOnLevelUnloaded()
{
#if WITH_EDITOR
auto CurrentLevel = UGameplayStatics::GetStreamingLevel(GetWorld(), LoadedLevelName);
if (CurrentLevel && !CurrentLevel->IsLevelLoaded())
{
// To avoid warnings in the editor, should be moved to Identity at this point.
FLevelUtils::SetEditorTransform(CurrentLevel, FTransform());
}
#endif
OnLevelUnloaded.Broadcast();
}
Tested inside and outside the editor.
Hope this helps someone.