Package Async Load VS OpenLevel VS Travel

Hi guys,

We’re expecting some issues with loading UWorld asynchronously and we’d like to get some feedbacks on what we’re doing.

We have a few maps, but the issue we get happens when going from a MainMenu map to a GameWorld map.

Both maps are completely independent, they have their own persistent level, game modes, player controller, etc.

The game is single-player and each game worlds will have its own world settings, blueprints, game modes, controllers, etc.

The way we’re handling the async loading is done through the following code relying in our game-specific game instance class:

LoadPackageAsync(LevelPathStr, FLoadPackageAsyncDelegate::CreateUObject(this, &UMyGameInstance::FinishedStreamingLevel));

void UMyGameInstance::FinishedStreamingLevel(const FName& PackageName, UPackage* LevelPackage, EAsyncLoadingResult::Type Result)
{
       PackageBeingLoaded = LevelPackage; // UProperty() in .h

       UWorld * world = UWorld::FindWorldInPackage(LevelPackage);
       check(world != nullptr);

       WorldBeingLoaded = world; UProperty() in .h

       UGameplayStatics::OpenLevel(this, LevelPathToLoad);
}

And we have another callback that we gets called through the FWorldDelegates::OnPostWorldInitialization:

void UMyGameInstance::WorldAdded(UWorld* world)
{
       if (WorldBeingLoaded == nullptr)
              return;

       check(WorldBeingLoaded == world);

       WorldBeingLoaded = nullptr;
       PackageBeingLoaded = nullptr;
}

The initial issue was that we were hitting a random crash when loading the game world, which seemed to be related to a world being destroyed within an unclean path:

void FPhysicsIntegration2D::ShutdownPhysics()
{
   FWorldDelegates::OnPreWorldInitialization.Remove(OnWorldCreatedDelegateHandle);
   FWorldDelegates::OnPreWorldFinishDestroy .Remove(OnWorldDestroyedDelegateHandle);

   check(WorldMappings.Num() == 0);
}

After investigation, we find out that without creating a reference to the package & world within the async load callback, all the assets seemed to be garbage collected during the OpenLevel process. We ended up with wholes in FUObjectHashTables for new assets within the new package including the world itself.

This is why we added the caching & caching cleanup on post-world initialization.

However, doing so, we get the another issue: The world always loads without crashing but it only loads the persistent level, so player falls…. And the other levels actually never shows up.

When the player fall, we tried RestartLevel and the everything is ok and the sub-levels streams in.

We also tried a completely different approach using SeamlessTravel (instead of UGameplayStatics::OpenLevel), but as far as we understood, this path is to stream from one level to another when both levels are in the same world or at least when player controllers, game mode, etc should all be transferred to the newly loaded world, which is not what we need here.

One last thing, we did tried to make this work in PIE world and for various reasons, it didn’t end well. I could elaborate on that too but reading through the posts, it seems that its not completely supported yet. We opted to use UGameplayStatics::OpenLevel directly since it didn’t really matter.

All of this is a WIP and we might not be doing things the right way as we’re kinda new to UE. We also used the following references as source of information:

Any help will be greatly appreciated!

Cheers,

Did you have any luck with this? I’m trying to do the same thing to prevent being kicked out to the steam vr compositor when the frame rate tanks from loading a level.

Looks like we need to upgrade our project to 4.16, thanks for the response!

Yup everything finally works out fine on our side, but we had to add some bugfixes within UE4 code. I believe all those fixes are in 4.16.