Map Changes
Why Map Changes Are Different in Fusion
Unreal developers reach for ServerTravel and ClientTravel for map changes. Under Fusion there is no canonical server, so ServerTravel has nothing to anchor on — map authority anchors to the Master Client instead. The Master Client decides the next world for the room; every other peer follows that decision or branches off locally. See Concepts for the Master Client role.
The Master Client picks the next world via UFusionOnlineSubsystem::ChangeWorld. Non-master peers either follow that decision (room-wide travel, replicated through Fusion) or branch off locally via ClientTravel (single-peer travel, not replicated). Never call ServerTravel under Fusion — it has no meaningful target.
On clients use either UGameplayStatics::OpenLevel or APlayerController::ClientTravel. Both regular travel and seamless travel is supported. Fusion will not override a world or level change. A client can travel to a different world than what is specified from the MasterClient. Re-syncing a world is then handled by the developer by travelling to the correct world and calling UFusionOnlineSubsystem::AttachCurrentMap
ChangeWorld and ChangeWorldByName
UFusionOnlineSubsystem::ChangeWorld(TSoftObjectPtr<UWorld>, WorldContextObject) is the Master-Client-only call that schedules the next world for the whole room. It takes a soft-object pointer to the target UWorld and replicates the request to every other peer, so they all load the same map.
ChangeWorldByName(FString WorldName, WorldContextObject) is the string-path overload that ChangeWorld funnels into. Both forms transition the local client to EMapState::MasterClientChangeWorld and replicate the request to remote peers.
C++
OnlineSubsystem->ChangeWorld(NextLevel, this);
The Map-Load Callback Sequence
Three multicast delegates fire on UFusionOnlineSubsystem in order during a map change:
OnMapLoadRequested— a load has been scheduled; the client knows where it is going next.OnMapLoadPerform— fires only when the project opted out of auto-load; the handler is expected to issue the actual map open.OnMapLoadDone— the new world is live and ready for actors to attach.
OnMapLoadPerform is only broadcast when UFusionOnlineSubsystemSettings::LoadMapAutomatically is false, or when Fusion.LoadMapBehaviourOverride forces manual mode (see Level Streaming). In manual mode the client stays in EMapState::IsLoading until the project's handler calls the actual map open — which is the moment for a loading screen, an async asset stream, or any other custom transition.
C++
void UMyGameInstance::Init()
{
Super::Init();
UFusionOnlineSubsystem* Subsystem = GetSubsystem<UFusionOnlineSubsystem>();
Subsystem->OnMapLoadRequested.AddDynamic(this, &UMyGameInstance::HandleMapLoadRequested);
Subsystem->OnMapLoadPerform.AddDynamic(this, &UMyGameInstance::HandleMapLoadPerform);
Subsystem->OnMapLoadDone.AddDynamic(this, &UMyGameInstance::HandleMapLoadDone);
}
| Order | Callback | Fires when | EMapState while waiting |
|---|---|---|---|
| 1 | OnMapLoadRequested |
Always — a map load has been scheduled. | MasterClientChangeWorld |
| 2 | OnMapLoadPerform |
Only in manual mode (LoadMapAutomatically=false or Fusion.LoadMapBehaviourOverride=2). Handler must drive the actual open. |
IsLoading |
| 3 | OnMapLoadDone |
Always — the new world is live and ready for actors to attach. | Active (new world) |
StopFusionSession
UFusionOnlineSubsystem::StopFusionSession has two overloads. The parameterless StopFusionSession() tears down the underlying UFusionClient via Shutdown(). The BP-callable StopFusionSession(WorldContextObject, TSoftObjectPtr<UWorld> ReturnWorld) does the same teardown and then OpenLevels back to a non-networked map.
StopFusionSession() is also the path the async actions take internally. UFusionLeaveRoomAsync, UFusionDisconnectFromPhotonAsync, and UFusionConnectToPhotonAsync all call it when they need to drop the Fusion runtime — there is no separate teardown to call.
Prefer the ReturnWorld overload when leaving multiplayer back to a main menu. Without it, the player stays on the now-detached networked map, which keeps networked actors and components around in a degraded state. With ReturnWorld, the player lands on a clean offline level immediately.
RestartGame Caveats
AGameMode::RestartGame() works under Fusion but only behaves correctly when invoked on the Master Client. Calling it on a non-master peer triggers a local ClientTravel that does not replicate to the rest of the room — the calling peer travels alone and the others see them disappear. See Game Classes for the broader AGameMode story.
The recommended split: the Master Client calls UFusionOnlineSubsystem::ChangeWorld to rotate the whole room. Non-master clients call UFusionHelpers::FusionClientTravel only when they want to leave the room locally — for example, returning to the main menu after a defeat.
Avoid AGameMode::RestartGame() for round-restart flows. Replicate the intent through gameplay state — typically the MatchState on the GameState (see Game Classes) — and let the Master Client drive the actual ChangeWorld from its handler.
Seamless vs Non-Seamless Travel
Seamless travel on the Master Client must originate from UFusionOnlineSubsystem::ChangeWorld. Calling UWorld::SeamlessTravel directly from any other state can lead to unexpected consequences and is not a code path we recommend.
Enable AGameMode::bUseSeamlessTravel only after confirming the transition map is non-networked (its actors do not carry UFusionActorComponent).
On none Master Clients its preferred to use UFusionOnlineSubsystem::ClientTravel, however normal APlayerController::ClientTravel or UWorld::SeamlessTravel will work. But these calls do not have the builtin guards that checks connection status and what client type is set.
Preserving PlayerState Across Travel
Fusion follows Unreal's convention on APlayerState lifecycle. See Game Classes for the APlayerState story.
Store any travel-critical per-player data on APlayerState, not on the controller or pawn. Controllers and pawns are re-spawned by the new map's GameMode and lose their state across travel.
The rejoin correlation mechanism is governed by Fusion's player lifecycle, not by the stock-UE address lookup. Fusion will attempt to match the previous internal player index when a player reconnects. This index is what internally gets matched to the APlayerState found in InactivePlayerArray on the game state.