Keywords: UE4, Networking, Dedicated Server,ClientTravel, ServerTravel, UEngine::Browse


Difference between ServerTravel and ClientTravel
  • ServerTravel also informs the clients to move along with the server.
  • ClientTravel will be called locally for the client to load a new map. or connect to ip.
  • Browse can load local map via LoadMap ( not for multiplayer ) but there are more things happening in this method. I also want to know more about what it does and what it should be used for.
  • LoadMap should also load a map for a local client

Browse, LoadMap, ServerTravel and ClientTravel?

What’s the different between absolute travel and relative travel?

What is the difference between ServerTravel and OpenLevel?

PlayerController->ClientTravel() (Connect to remote server)

Seamless and non-seamless travel


How to pass arguments from Client to Server

When execute PlayerController->ClientTravel, default URL is like this:

FString Address = TEXT("");

If want to pass arguments to Server when logining, URL format is like this:

FString Address = FString::Printf(TEXT(""), *Param1, *Param2);
How to parse arguments sent by Client on Server

Overrice function InitNewPlayer() in GameMode, then parse arguments like this:

FString AMyGameMode::InitNewPlayer(APlayerController* NewPlayerController, const FUniqueNetIdRepl& UniqueId, const FString& Options, const FString& Portal = TEXT(""))
    FString Param1 = UGameplayStatics::ParseOption(Options, TEXT("Param1"));
    FString Param2 = UGameplayStatics::ParseOption(Options, TEXT("Param2"));

Official Doc: Passing Arguments To Server During Connection

How does Server informs Clients which are connected to Server to travel map

Execute ClientTravel on Server:

void AMyGameModeBase::PostLogin(APlayerController* NewPlayer)
    FString URL = TEXT("/Game/Maps/TestMap");
    NewPlayer->ClientTravel(URL, TRAVEL_Absolute);

This way works right for travelling to new map, but Client would also disconnect to Server. It means that the NetMode of all Actors in Client would be set as NM_Standalone.

How to use ServerTravel

A common use case is starting a server in a lobby level. Clients connect to this lobby level and choose loadout and character, for example. When ready, the server triggers a ServerTravel, which transitions all clients into the main game level.

When ServerTravel is triggered, the server tells all clients to begin to ClientTravel to the map specified. If the ServerTravel is seamless then the client maintains its connection to the server. If it’s not seamless then all the clients disconnect from the server and reconnect once they have loaded the map. Internally, the server does a similar process: it loads in the new level, usually a game world for all the clients to play on, and begins accepting player spawn requests once ready.

Reference: Map travel


See the usage of APlayerController->ClientTravel() in Offical Project ShooterGame.

Seamless travel

After seamless travel AGameModeBase::GenericPlayerInitialization(AController* Controller) and AGameModeBase::HandleStartingNewPlayer(), Gets called for the client.


Travelling API in GameMode


APlayerController* AGameModeBase::ProcessClientTravel(FString& FURL, FGuid NextMapGuid, bool bSeamless, bool bAbsolute)
    // We call PreClientTravel directly on any local PlayerPawns (ie listen server)
    APlayerController* LocalPlayerController = nullptr;
    for (FConstPlayerControllerIterator Iterator = GetWorld()->GetPlayerControllerIterator(); Iterator; ++Iterator)
        if (APlayerController* PlayerController = Iterator->Get())
            if (Cast<UNetConnection>(PlayerController->Player) != nullptr)
                // Remote player
                PlayerController->ClientTravel(FURL, TRAVEL_Relative, bSeamless, NextMapGuid);
                // Local player
                LocalPlayerController = PlayerController;
                PlayerController->PreClientTravel(FURL, bAbsolute ? TRAVEL_Absolute : TRAVEL_Relative, bSeamless);

    return LocalPlayerController;


void AGameModeBase::ProcessServerTravel(const FString& URL, bool bAbsolute)

    // Force an old style load screen if the server has been up for a long time so that TimeSeconds doesn't overflow and break everything
    bool bSeamless = (bUseSeamlessTravel && GetWorld()->TimeSeconds < 172800.0f); // 172800 seconds == 48 hours

    FString NextMap;
    if (URL.ToUpper().Contains(TEXT("?RESTART")))
        NextMap = UWorld::RemovePIEPrefix(GetOutermost()->GetName());
        int32 OptionStart = URL.Find(TEXT("?"));
        if (OptionStart == INDEX_NONE)
            NextMap = URL;
            NextMap = URL.Left(OptionStart);

    FGuid NextMapGuid = UEngine::GetPackageGuid(FName(*NextMap), GetWorld()->IsPlayInEditor());

    // Notify clients we're switching level and give them time to receive.
    FString URLMod = URL;
    APlayerController* LocalPlayer = ProcessClientTravel(URLMod, NextMapGuid, bSeamless, bAbsolute);

    UE_LOG(LogGameMode, Log, TEXT("ProcessServerTravel: %s"), *URL);
    UWorld* World = GetWorld();
    World->NextURL = URL;
    ENetMode NetMode = GetNetMode();

    if (bSeamless)
        World->SeamlessTravel(World->NextURL, bAbsolute);
        World->NextURL = TEXT("");
    // Switch immediately if not networking.
    else if (NetMode != NM_DedicatedServer && NetMode != NM_ListenServer)
        World->NextSwitchCountdown = 0.0f;


Official Docs

Travelling in Multiplayer