pre-load level

Hey all,

I’ve been trying to get this working for a few days now, and I’ve looked into source code and into forum and answerhub trying to get the desired result but sadly no luck.

Generally, we need to load a level/map/world and all of it’s contents permanently or prematurely into the memory so that it loads faster once we call the actual OpenLevel function.

Every combination of results and tests we did based on answer hub, forums, and just trying ourselves seem to have one issue or another.
Currently our solution is based on -> How to open level asynchronously, without visible after load? - C++ Gameplay Programming - Unreal Engine Forums

However, that has the following issues;

When we call LoadPackageAsync(or non async for that matter), add it to root or some UProperty TArray it correctly loads it into the memory and if we call “open level” afterwards it instantly loads it from memory if we try this in editor.
When we use the same function, and same logic but try to package or launch standalone, it also loads successfully into memory but it throws the following warning;


[2018.10.22-19.42.29:752][595]LogNet: Warning: Travel Failure: [ClientTravelFailure]: Failed to load package '/Game/ModSci_Engineer/Maps/Example_Stationary_2'
[2018.10.22-19.42.29:752][595]LogNet: TravelFailure: ClientTravelFailure, Reason for Failure: 'Failed to load package '/Game/ModSci_Engineer/Maps/Example_Stationary_2''

After attaching debugger and checking why it fails, it fails exactly on UEngine::LoadMap, afterwhich it fails at the following



// This can still be null if the package name is ambiguous, for example if there exists a umap and uasset with the same
        // name.
        if (NewWorld == nullptr)
        {
            // it is now the responsibility of the caller to deal with a NULL return value and alert the user if necessary
            Error = FString::Printf(TEXT("Failed to load package '%s'"), *URL.Map);
            return false;
        }


After debugging over the steps it takes to get there, in UWorld::FindWorldInPackage(WorldPackage), it fails to find a world. It only has the packagemetadata inside of the package when it tries to iterate over the PotentialWorlds inside the aforementioned function. If we breakpoint the FindWorldInPackage without pre-asyncloading the level, it does find the world in the package.


When we call LoadPackageAsync, without adding it to root or a UProperty TArray, it does not fail to load the map, however does not fast-load the level either in packaged or standalone.
When we call the load without adding to root or uproperty in editor, it does fast-load the level.

Either we’re doing something wrong, or it’s not possible in the way that we’re trying it. We do need to keep the level in the memory so it can fast-load, and we can’t use level streaming because it’s 2 complete different levels(empty load level, and play level).

Does someone have any insight into how we can load it into memory, so that the level loads much faster outside the editor?

We have tried using the asset manager, to pre-load certain meshes, textures, etc, however that didn’t help loading times either.

Keep a pointer to the map asset in your GameInstance;

​​​​​​On GameInstance’s Init(), do:



MapAssetPtr->GetAsset();


That should load everything to memory even if you didn’t try to load/AsyncLoad the map yet.
** The pointer to map asset should be a *FAssetData *struct.

I’ve tried your method, but only the first time open level working as fast load, later if I want to open another level, crashes the engine in the packaged game. All the method(like the async load and add to root or load it from primary asset or keep a reference) I tried is working in PIE, but not in packaged game build.

Later I found that every time I open another level, in the packaged game, engine tend to unload all the current loaded map data, if this level data was pre loaded by myself, whether it is root or not, crash report tells me this level is not cleaned up by garbage collection.

Also I found the FAssetData struct does not hold any in memory data, but a reference to the asset in memory or in the hard drive, keep the loaded object is caching the data, but crash the engine when it open another level(unload current pre cached level)



Fatal error: [File:D:\Build\++UE4\Sync\Engine\Source\Runtime\Engine\Private\UnrealEngine.cpp] [Line: 12966] World /Game/Maps/LevelB.LevelB not cleaned up by garbage collection! World /Game/Maps/LevelB.LevelB [target] (standalone) TestGameInstance_C /Engine/Transient.GameEngine_0:TestGameInstance_C_0 (ObjectProperty /Game/Test/TestGameInstance.TestGameInstance_C:NewVar_14) GameEngine /Engine/Transient.GameEngine_0 (root) (ObjectProperty /Script/Engine.GameEngine:GameInstance)

UE4Editor_Core!FDebug::AssertFailed() [d:\build\++ue4\sync\engine\source\runtime\core\private\misc\assertionmacros.cpp:417]
UE4Editor_Engine!UEngine::VerifyLoadMapWorldCleanup() [d:\build\++ue4\sync\engine\source\runtime\engine\private\unrealengine.cpp:12966]
UE4Editor_Engine!UEngine::LoadMap() [d:\build\++ue4\sync\engine\source\runtime\engine\private\unrealengine.cpp:12000]
UE4Editor_Engine!UEngine::Browse() [d:\build\++ue4\sync\engine\source\runtime\engine\private\unrealengine.cpp:11527]
UE4Editor_Engine!UEngine::TickWorldTravel() [d:\build\++ue4\sync\engine\source\runtime\engine\private\unrealengine.cpp:11725]
UE4Editor_Engine!UGameEngine::Tick() [d:\build\++ue4\sync\engine\source\runtime\engine\private\gameengine.cpp:1353]
UE4Editor!FEngineLoop::Tick() [d:\build\++ue4\sync\engine\source\runtime\launch\private\launchengineloop.cpp:3699]
UE4Editor!GuardedMain() [d:\build\++ue4\sync\engine\source\runtime\launch\private\launch.cpp:174]
UE4Editor!GuardedMainWrapper() [d:\build\++ue4\sync\engine\source\runtime\launch\private\windows\launchwindows.cpp:145]
UE4Editor!WinMain() [d:\build\++ue4\sync\engine\source\runtime\launch\private\windows\launchwindows.cpp:276]
UE4Editor!__scrt_common_main_seh() [f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl:283]
kernel32
ntdll


Any idea? Thanks in advance.

Well… You’re supposed to manage the pointers yourself, nullifying them once the level you need was already loaded.

Nullifying the pointer means it will being garbage collected, what I want is just keep the package/world asset in memory, I can fast travel in and travel out, and then I can fast travel in again without load the level again…