Loading an already existing streaming level, the tricky part is to get the level
instance, then you just have to kick loading in. This requires your levels to be in the level browser of your persistent level to work properly.
void UMyGameInstance::LoadLevel(const FName LevelName)
{
ULevelStreaming* CurrentLevel = FindAndCacheLevelStreamingObject(GetWorld(), World);
if (CurrentLevel)
{
// TODO: Add delegates
CurrentLevel->bShouldBeLoaded = true;
CurrentLevel->bShouldBeVisible = true;
CurrentLevel->bShouldBlockOnLoad = false;
}
}
ULevelStreaming* UMyGameInstance::FindAndCacheLevelStreamingObject(const FName LevelName, UWorld* InWorld)
{
// Search for the level object by name.
if (LevelName != NAME_None)
{
const FString SearchPackageName = MakeSafeLevelName(LevelName, InWorld);
for (ULevelStreaming* LevelStreaming : InWorld->StreamingLevels)
{
// We check only suffix of package name, to handle situations when packages were saved for play into a temporary folder
// Like Saved/Auto-saves/PackageName
if (LevelStreaming &&
LevelStreaming->GetWorldAssetPackageName().EndsWith(SearchPackageName, ESearchCase::IgnoreCase))
{
return LevelStreaming;
}
}
}
return NULL;
}
FString UMyGameInstance::MakeSafeLevelName(const FName& InLevelName, UWorld* InWorld)
{
// Special case for PIE, the PackageName gets mangled.
if (!InWorld->StreamingLevelsPrefix.IsEmpty())
{
FString PackageName = InWorld->StreamingLevelsPrefix + FPackageName::GetShortName(InLevelName);
if (!FPackageName::IsShortPackageName(InLevelName))
{
PackageName = FPackageName::GetLongPackagePath(InLevelName.ToString()) + TEXT("/") + PackageName;
}
return PackageName;
}
return InLevelName.ToString();
}
NOTE: All these examples are missing the level loaded/shown/unloaded/hidden delegates for clarity