`

Multiplayers Level Streaming How-Tos

 
阅读更多

 

Travelling in multoplayer Seamless and non-seamless travel

seamless travel is a non-blocking operation, while non-seamless will be a blocking call.

When a client executes a non-seamless travel, the client will disconnect from the server and then re-connect to the same server, which will have the new map ready to load.

It is recommended that UE4 multiplayer games use seamless travel when possible. It will generally result in a smoother experience, and will avoid any issues that can occur during the reconnection process.

There are three ways in which a non-seamless travel must occur:

  • When loading a map for the first time

  • When connecting to a server for the first time as a client

  • When you want to end a multiplayer game, and start a new one

There are three main function that drive travelling: UEngine::Browse, UWorld::ServerTravel, and APlayerController::ClientTravel. These can be a bit confusing when trying to figure out which one to use, so here are some guidelines that should help:

UEngine::Browse,

  • Is like a hard reset when loading a new map.

  • Will always result in a non-seamless travel.

  • Will result in the server disconnecting current clients before travelling to the destination map.

  • Clients will disconnect from current server.

  • Dedicated server cannot travel to other servers, so the map must be local (cannot be URL).

UWorld::ServerTravel,

  • For the server only.

  • Will jump the server to a new world/level.

  • All connected clients will follow.

  • This is the way multiplayer games travel from map to map, and the server is the one in charge to call this function.

  • The server will call APlayerController::ClientTravel for all client players that are connected.

APlayerController::ClientTravel,

  • If called from a client, will travel to a new server

  • If called from a server, will instruct the particular client to travel to the new map (but stay connected to the current server)

Enable seamless travel

To enable seamless travel, you need to setup a transition map. This is configured through the UGameMapsSettings::TransitionMap property. By default this property is empty, and if your game leaves this property empty, an empty map will be created for the transition map.The reason the transition map exists, is that there must always be a world loaded (which holds the map), so we can't free the old map before loading the new one. Since maps can be very large, it would be a bad idea to have the old and new map in memory at the same time, so this is where the transition map comes in.So now we can travel from the current map to the transition map, and then from there we can travel to the final map. Since the transition map is very small, it doesn't add much extra overhead while it overlaps the current and final map.

Once you have the transition map setup, you set AGameModeBase::bUseSeamlessTravel to true, and from there seamless travel should work!

 

Seamless travel flow

Here is the general flow when executing seamless travel:

  1. Mark actors that will persist to the transition level (more below)

  2. Travel to the transition level

  3. Mark actors that will persist to the final level (more below)

  4. Travel to the final level

Persisting Actors across Seamless Travel

When using seamless travel, it's possible to carry over (persist) actors from the current level to the new one. This is useful for certain actors, like inventory items, players, etc.

By default, these actors will persist automatically:

  • The GameMode actor (server only)

    • Any actors further added via AGameModeBase::GetSeamlessTravelActorList

  • All Controllers that have a valid PlayerState (server only)

  • All PlayerControllers (server only)

  • All local PlayerControllers (server and client)

    • Any actors further added via APlayerController::GetSeamlessTravelActorList called on local PlayerControllers

 

 

 I am just curious about how level streaming works in multiplayer. How can it we sync up logic and data even when the 'level' isnt loaded. Especially with destructible assets. And is there an 'LOD' system for entire levels, instead of level streaming?

 LODs are used in Static Meshes and Materials, so I'm not sure what you mean about using it for entire levels. For Multiplayer, LOD should only change for the player based on the player's position relative to the Actor and not other players' positions.

 

Is it possible to do level streaming in a multiplayer game?

Level streaming does function in multiplayer games. However, when any player steps into a level streaming volume, the connected level will load for every player, even though the other players are not inside that volume. Logic for streaming volumes is hardcoded to replicate streaming state changes to all clients, so level streaming in a multiplayer game may not be useful without changing source code.

You can, however, achieve a similar effect with some creative use of Blueprints and Trigger Volumes.

This way the streaming level will only be streamed on the client when the local character steps into the Trigger Volume.

 

Possible to level-stream infinite space?

 I've read that the level streaming in ue4 re-bases the world origin so that you can move past the world bounds without getting floating point inaccuracy issues, but as far as I can tell, streamed levels need to be in a pre-defined place.Would it be be possible to somehow use level streaming to rebase the world origin whenever you get near the world bounds, so you could travel infinitely through blank space? ( in all directions )

 That's not quite what level streaming is, what you're thinking of is World Composition. Level streaming allows you to combine different levels but doesn't manage things like origin rebasing. I don't think it contains the ability, but realistically you could make something that appears infinite where it just randomizes how you connect to different maps. Just note, that doesn't work for multiplayer, you have to make your own solution for multiplayer games that go beyond a certain distance.

 

Big Worlds and Multiplayer

Right now world origin shifting is not supported in the multiplayer games. Here are two solutions that can be implemented for your specific needs:

  1. Implement your own server solution. MMO licensees mostly do this.

  2. Implement some layer between clients and unreal dedicated servers which will transform shifted absolute positions from the clients and route them to the right dedicated server, which only holds part of the world where client is.

However if you disable world origin, shifting you can run a tiled world with a dedicated server. Dedicated servers will load all distance dependent levels, and each connected client will work as usual loading only level that satisfy streaming distance settings. A server holds a list of visible levels for each client and filters Actor replication by this list.

 

 

 

Contrary to what I read, the PlayerState and GameState objects are not actually saved from one map to the next.

More accurately new ones are created and relevant data copied across.

Didn't look too far into GameState, but for PlayerState you have to manually specify how to copy your data to the new PlayerState when seamless travel occurs:

In your custom PlayerState class, override CopyProperties to copy all your values across to the new object.

  1. virtualvoidCopyProperties(classAPlayerState*PlayerState);
  2. voidAMyPlayerState::CopyProperties(classAPlayerState*PlayerState)
  3. {
  4. APlayerState::CopyProperties(PlayerState);
  5. AMyPlayerState* myPlayerState =Cast<AMyPlayerState>(PlayerState);
  6. if(myPlayerState)
  7. {
  8. // Copy all the properties that you want to keep across map change here
  9. myPlayerState->variable = variable;
  10. }
  11. }
  12.  

The only other requirement is actually calling ServerTravel on the World to change map and setting bUseSeamlessTravel = true on your GameMode.

Surprised that there seems to be no documentation regarding any of this.

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics