x

Search in
Sort by:

Question Status:

Search help

  • Simple searches use one or more words. Separate the words with spaces (cat dog) to search cat,dog or both. Separate the words with plus signs (cat +dog) to search for items that may contain cat but must contain dog.
  • You can further refine your search on the search results page, where you can search by keywords, author, topic. These can be combined with each other. Examples
    • cat dog --matches anything with cat,dog or both
    • cat +dog --searches for cat +dog where dog is a mandatory term
    • cat -dog -- searches for cat excluding any result containing dog
    • [cats] —will restrict your search to results with topic named "cats"
    • [cats] [dogs] —will restrict your search to results with both topics, "cats", and "dogs"

How do I use PrepareMapChange/CommitMapChange?

I am currently loading a level with UGameplayStatics::OpenLevel(GetWorld(), mapToLoad, 1, "");

however, this unloads my whole game and reloads it again. I need the game to simply keep my current data but move into a new map/location. I have had a look around and the PrepareMapChange states that "... GameModes where the game state should be preserved through a transition." which seems to be what I need.

However, I cannot seem to get this working as I get an error ("LogEngine:Warning: PREPAREMAPCHANGE: Couldn't find package for level 'Room01'") when trying to give the array my map names: Room01, Room02.. with each of them as a map file in the content/maps. I feel I am missing something so can anyone give me any pointers of how I should be using this correctly?

Product Version: Not Selected
Tags:
more ▼

asked May 21 '14 at 11:56 AM in C++ Programming

avatar image

Dune
1.8k 52 36 200

avatar image Dune May 27 '14 at 10:08 AM

Anybody used this method at all? Tried to find more information about it but have been struggling. Currently use OpenLevel(...) but it freezes my game (Could do with a loading screen that has some animating icon on) and also re-initializes all my game mode and variables.

avatar image Shadowriver May 27 '14 at 11:22 AM

You tried with extension *.umap

avatar image Dune May 27 '14 at 12:22 PM

Yeah, I tried the full file path and it does seem to find it and being loading it with the prepare map change. I put a few checks in and it seems to constantly be loading the maps data up in the background while I can still do whatever I need to (animating loading screens), but when I call CommitMapChange, it seems to do nothing at all and there is simply no output to find out why it doesn't work.

avatar image Dune Jun 02 '14 at 09:20 AM

Still having some trouble with getting this concept working. I am still trying to find a way to load/unload different maps but I am currently still using OpenLevel - Which does work, however the game freezes and the takes sometimes what seems forever to load a level which isn't suitable really. Is there a specific approach I need to be looking at which suits my needs?

avatar image Vicky3 Jul 02 '15 at 06:51 PM

Hi! Same problem here. I do: TArray* levels = new TArray < FName >; levels->Add("/Game/Maps/RoomNight"); GetWorld()->PrepareMapChange(*levels); which seems to work (with a wrong path there is an error in log). But when I call GetWorld()->CommitMapChange(); the game freezes although IsMapChangeReady() is true. Does anyone see my fault?

avatar image Elseware-Experience Jul 04 '18 at 11:05 AM

Sorry to dig this post 3years later but this is really interesting for me. Everything seems to be working just fine except for one thing ! The virtual void PostCommitMapChange(); That I included in my game mode is never called. It doesnt seem to be overridable too so I guess something changed in the use of this whole system. Could someone help me out figuring this out ? Else I guess I will simply call the gamemode within the class and tell me to go on.

(comments are locked)
10|2000 characters needed characters left

1 answer: sort voted first

I know this is old, but I'll answer for any future people who have the same question.

Using PrepareMapChange/CommitChangeMap:

Call GetWorld()->PrepareMapChange and give it a list of maps (FName list) starting with the main (persistent level) first, followed by any sublevels that need to be loaded at the spawn point. Example:

 TArray<FName> Levels;
 Levels.Add(MainLevel);
 Levels.Add(Sublevel1);
 Levels.Add(Sublevel2);

The FNames must be in the form:

 FName MainLevel = "/Game/Maps/MyLevelName";

Note that the extension is not being used, and we use "/Game" rather than "/Content". If you have a filepath, you can covert it to the needed format, called a "Long Package Name", by calling:

 FPackageName::FilenameToLongPackageName(MyFilePath)

If you neglect to add a needed sublevel to the list sent to PrepareMapChange, the call to CommitMapChange will block for however long it takes to load and set up the neglected level.

To check to see if the maps are done preloading use:

 if(GetWorld()->IsMapChangeReady && !IsAsyncLoading())

That second part is important because IsMapChangeReady tells you if the levels sent in the list to PrepareMapChange are ready, but not if any sublevels or assets those maps reference are ready.

When done call:

 GetWorld()->CommitMapChange();

It's important NOT to call the GEngine version of the same file. The UWorld version makes sure the call is done the right way.

When CommitMapChange is done, there will be a callback to GameMode::PostCommitMapChange(). Teleport the player and do any setup necessary for the new level there. Note that TeleportTo will not change the orientation of the Player, so you need to set that manually by calling

 MyPlayerController->SetControlRotation(LevelPlayerStart->GetActorRotation()); 


How long the switchover takes after calling CommitMapChange depends on how long the garbage collection takes when clearing the old level. If you're exiting a small level, then the transition is very small. On my tests with large levels, the switch over took about a second and a half. Usually a quick fade-out, CommitMapChange, fade-in can easily hide the transition.

This method will NOT work in "Play In Editor" mode (PIE). You must run it in Standalone mode to see it.

Hope this helps.

...

EDIT: To make this pipeline work in PIE mode:

1) In EditorEngine.cpp (Engine\Source\Editor\UnrealEd\Private):

In UEditorEngine::Tick:

Look for the first inner loop that contains the line:

FWorldContext &PieContext = *ContextIt;

Near the end of that loop add:

  ConditionalCommitMapChange(PieContext.World());

2) In UnrealEngine.cpp (Engine\Source\Runtime\Engine\Private):

In UEngine::CommitMapChange:

After:

if(bWasFound) {

Add:

  if (Context.WorldType == EWorldType::PIE)
       StreamingLevel->RenameForPIE(Context.PIEInstance);
more ▼

answered Oct 19 '15 at 11:54 PM

avatar image

rantrod
1.5k 47 47 213

avatar image MADMarkQc Nov 12 '15 at 12:18 AM

Hi rantrod.

Thanks for this detailed explanation, I've made some progress, but I still have some issues.

First of all, after adding the couple of code lines you suggested, I wasn't able to make this technique work in PIE. By the way, they are 2 inner loop that contains the line FWorldContext PieContext = *ContextIt;

Second problem: The steps you explain successfully loads the Persistent Map i want to load, but not the sub-levels.

Third Problem: When I Load the Map, my old Map is not unloaded. So I have 2 Level Blueprints that are running at the same time. How should I unload the old Map?

Thanks for you help!

avatar image rantrod Nov 21 '15 at 06:00 AM

The first occurrence of "FWorldContext PieContext = *Contextit;" is the correct one.

The only reason a sub-level would not show up even if it's added into the array you send to PrepareMapChange, is if there is no reference to that sub-level in the segment you're loading into (i.e. they get garbage collected).

The old levels get garbage collected when you no longer reference them.

If you need more of a "clean slate" approach where everything you used to have is deleted, replaced by a new level, and you're put into the new level's game start, then I would recommend a different approach.

avatar image Azarus Dec 10 '16 at 07:08 PM

Great tutorial but i would love to see some full code so its easier for others just to copy paste this or something :)

Thanks anyways really appriciate it.

avatar image Azarus Dec 15 '16 at 05:28 PM

Also, if you want a nice UI too selelect your levels instead of write them as strings you can use:

 TAssetPtr<UWorld> LevelAsset;

And get the package name like this:

 FString LevelPath = LevelAsset.GetLongPackageName();

And add it to the levels array:

 Levels.Add(*LevelPath);

(comments are locked)
10|2000 characters needed characters left
Your answer
toggle preview:

Up to 5 attachments (including images) can be used with a maximum of 5.2 MB each and 5.2 MB total.

Follow this question

Once you sign in you will be able to subscribe for any updates here

Answers to this question