I have tryed Streaming Levels, but this is not what i need. Because if i make level - Steamable and then use UGameplayStatics::LoadStreamLevel, then level is loaded, but GameMode, PlayerController and HUD is not changed. I need it to be changed, like when normal load map.
I need something like UGameplayStatics::OpenLevel, but with async load, and with bMakeVisibleAfterLoad = false.
I have MainMenu, CharacterCreationMenu and GameWorld.
When i start game i am inside MainMenu, then i press login, and i go into CharacterCreationMenu, when i finished creating character i am going into GameWorld. (Typical game design).
But, i dont want game FREEZ, when i switch between this levels, i dont want LOADING.
So i want, when game starts, i am go into MainMenu, but, in the same time CharacterCreationMenu and GameWorld continue loading into memory asynchronously, while i am inside MainMenu.
I can try to do the following, i can use single GameMode, single PlayerController and HUD, for all MainMenu, CharacterCreationMenu and GameWorld, and make internally/manually switching functionality inside that classes, when i load another level. So, i could use level streaming, and manual HUD switching for example. I.e. i could make all 3 HUDS inside 1 HUD. Is it right solution? or there is async OpenLevel, like i need?
IMPROTANT NOTE: GameWorld probably is going to be WorldComposition, so i dont know yet, is it possible to use WorldComposition level like streaming level of another level. EDIT: no, WorldComposition cannot be streaming level: Is it possible to use level as streaming level, if it has own streaming levels? - UE4 AnswerHub
So, i have to OpenLevel(GameWorld) somehow, asynchronously.
The closest solution i found for now, is World->SeamlessTravel(), which is loading map synchronously, but at least with loading screen. Ofc this is not what i need, but for now this is all i found.
**I’ve tested a little SteamlessTravel, and i wanna say, that it is very bugged and very strange. First of all, SeamlessTravel can load streaming levels, regardless it’s PersistentLevel, with loading new GameMode and without unloading PersistentLevel GameMode (which is automatically becoming Garbage collected only after couple of minutes)… Second, is that all actors in editor’s World Outliner become deleted, wtf?. Third, as i understand, SeamlessTravel is somehow related with UE4 server handling, which i dont need, i need only client.
SteamlessTravel bug - when i load WorldComposition with SeamlessTravel, then sublevels are not loaded and if i try to load them with LoadSteamLevel - it fails.
FSeamlessTravelHandler contains similar functionality what i need, it has example of asynchronous map loading, using LoadPackageAsync. And also example of how to change CurrentWorld to LoadedWorld. But as i said it EDIT3, it is working with some bugs.
I think i can do smth that may help to my problem, i can load map package asyncronously (for example by using FStreamingManager or LoadPackageAsync) and keep pointer to that package to prevent garbage collecting, and then i can call OpenLevel when needed, potentially this can increase loading speed, because OpenLevel automatically determine if needed package is already loaded. This will not work so simple, because each map also contains many other asset references which also need to be loaded asyncly, so loading just single map package will give not much (UEngine::LoadPackagesFully, which is synchronous).
Some useful links about map changing:
I’ve tested PrepareMapChange and CommitMapChange, its kind of old version of level streaming, bugged and outdated i suppose.
There is no such functionality as i want in UE4.8 yet, i.e. async non-streamable map loading/precaching for later activation (LoadLevelAsync).
- SeamlessTravel (ServerTravel/ClientTravel) - working with bugs in PIE mode.
- PrepareMapChange and CommitMapChange - working with bugs in PIE mode.
- FStreamingManager - not supposed to be used in PIE mode, as i understand, thats strange, so its also bugged in PIE mode.
Use LoadPackageAsync function for precaching map and then manually prevent it from garbage collecting (AddToRoot maybe), and then use regular UGameplayStatics::OpenLevel when needed, it will automatically find precached map with specified name. Or just use UGameplayStatics::OpenLevel for now, without any async precache…