Network connection management
Understand different network connection types and configuration options available for multiplayer sessions.
Read time 5 minutesLast updated 12 hours ago
Players can create and join sessions using different network connection types and configuration options.
Types of network
By default, the following network connections types are available with the sessions system:- Direct network connection.
- Client-hosted solutions by Unity, using Relay or Distributed Authority. This type is the recommended best practice for peer-to-peer games played over the internet.
Class SessionOptions > MethodsINetworkHandlerConfigurable network options
You can override the default network options of your sessions, including both direct and relay-based networking. If you don't specify network options when calling theWithRelayNetwork()WithDirectNetwork()WithDistributedAuthorityNetwork()DirectNetworkOptions
Configure direct network connections withDirectNetworkOptionsWithDirectNetwork()SessionOption- ListenIp: The IPv4 or IPv6 address that you monitor for incoming IP connections.
- PublishIp: The IPv4 or IPv6 address to publish for other clients to connect to.
- Port: The port number used for both listening and publishing endpoints.
RelayNetworkOptions
Configure relay protocol-based network connections withRelayNetworkOptionsWithRelayNetwork()WithDistributedAuthorityNetwork()SessionOption- Protocol: Defines the network protocol that the Relay connection uses.
- Region: Forces a specific Relay region to be used, and skips autoselection from QoS results.
- PreserveRegion: If enabled, saves the relay region to session properties, and reuses it in case of host migration.
- User Datagram Protocol (UDP)
- Datagram Transport Layer Security (DTLS)
- Secure websocket (WSS)
Session and Netcode lifecycle separation
Starting with Multiplayer Services SDK version 1.2, you have the option to start the network connection after a session is created. The decoupled network lifecycle gives you greater flexibility and control over your game flow. After the host initiates the network connection, clients are notified and use the connection information shared by the host to start their own network connections. The connection information is shared with clients via session properties. The session'sNetwork- : Lets hosts control the network connection directly - start, stop, and manage it as needed. Available only through
IHostSessionNetwork; non-host clients cannot access this interface. To obtain anIHostSession, callIHostSession. This may fail if the caller is not the host.session.AsHost() - : Allows access only to network state and associated events. Can be accessed through the
IClientSessionNetworkinterface.ISession
- You can delay starting the network connection until certain conditions are met, for example:
- The host manually starts the game.
- The session reaches the maximum number of players.
- All players mark themselves as ready.
- As a host, you can stop the network connection at any time while keeping the session open, and restart it if needed.
Network connection management examples
The following examples demonstrate how to configure connection types, options, and lifecycle management for the networking solution tied to your session.Example: Creating a session with a client-hosted solution with overridden default relay options
The following example demonstrates how to create a session using a Unity client-hosted solution with overridden options provided to the relay allocation:The points from Example: Creating a session with a client-hosted solution also apply to this example, along with the following information:// When the region is specified, it forces the use of a specific Relay region, and skips QoS auto-selection.async Task StartSessionAsHost(string region = null){ var options = new SessionOptions { MaxPlayers = 2 }.WithRelayNetwork(new RelayNetworkOptions(RelayProtocol.Default, region, true)); // or WithDistributedAuthorityNetwork() to use Distributed Authority instead of Relay var session = await MultiplayerService.Instance.CreateSessionAsync(options); Debug.Log($"Session {session.Id} created! Join code: {session.Code}");}
- The class configures the session to start the relay connection using the platform-suggested
RelayNetworkOptionsprotocol with the providedDefaultparameter. Ifregionis set to true, the newly-elected host doesn't change the relay allocation region in the event of a host migration. If set to false, the region might change.PreserveRegion - If the region isn't passed as a parameter, the default value triggers a QoS query to determine the most optimal region for the relay allocation. For the list of available regions, refer to [Relay locations and regions][RelayRegions].
null
Example: Using a custom network handler
Advanced users can specify a custom network handler by implementing INetworkHandler, which overrides the default integration with Netcode for GameObjects and Netcode for Entities. You can provide integration with any third-party networking solutions when implementing theINetworkHandlervar options = new SessionOptions { MaxPlayers = 2 }.WithRelayNetwork().WithNetworkHandler(new CustomEntitiesNetworkHandler());
Example: Starting Netcode at a later time
In some games, you might want to delay starting the network connection and gameplay until certain conditions are met, for example, until all players have joined and are ready. The following example demonstrates how to delay the connection using the Session API.Consider the following details about how this example works:async Task StartSessionAsHost(){ var options = new SessionOptions { MaxPlayers = 4 }; // note the omitted `With<X>Network() call. var session = await MultiplayerService.Instance.CreateSessionAsync(options); session.PlayerJoined += OnPlayerJoined; session.Network.StartFailed += OnNetworkStartFailed; session.Network.StateChanged += OnNetworkStateChanged; Debug.Log($"Session {session.Id} created! Join code: {session.Code}"); void OnPlayerJoined(string playerId) { // verify if we have reached the max player count if (session.PlayerCount == session.MaxPlayers) { var networkOptions = new DirectNetworkOptions(ListenIPAddress.AnyIpv4, PublishIPAddress.LoopbackIpv4, 7777); // start the network once max player count have been reached _ = session.Network.StartDirectNetworkAsync(networkOptions); } } void OnNetworkStateChanged(NetworkState state) { switch (state) { case NetworkState.Starting: Debug.Log("Starting network..."); break; case NetworkState.Started: Debug.Log($"Network has started, listening on: {session.Network.NetworkInfo.ListenAddress}, " + $"and publishing on: {session.Network.NetworkInfo.PublishAddress} created!"); break; default: Debug.Log($"[{nameof(StartSessionAsHost)}] Network state has changed! New State:{state:G}"); break; } } void OnNetworkStartFailed(SessionError error) { // handle the error Debug.LogError($"Network start failed: {error:G}"); }}async Task JoinSessionAsClient(string sessionJoinCode){ // Join the session var session = await MultiplayerService.Instance.JoinSessionByCodeAsync(sessionJoinCode); Debug.Log($"Network state at the time of connection was: {session.Network.State:G}."); session.Network.StateChanged += OnNetworkStateChanged; void OnNetworkStateChanged(NetworkState state) { Debug.Log($"[{nameof(JoinSessionAsClient)}] Network state has changed! New State:{state:G}"); }}
-
Host():
StartSessionAsHost- By omitting the call to ,
WithDirectNetwork(), orWithRelayNetwork(), the session is created without starting a netcode connection right away.WithDistributedAuthorityNetwork() - The line creates the session, and makes the player the host.
var session = await MultiplayerService.Instance.CreateSessionAsync(options); - The next three lines subscribe to session lifecycle events: player joining, network state changes, and network start failures.
- The event handler checks if the maximum number of players is reached. In this example, the maximum number is four.
OnPlayerJoined - After the required number of players has joined the session, is called to start the network connection.
session.Network.StartDirectNetworkAsync(networkOptions) - The in this example are configured to listen on any IPv4 addresses (0.0.0.0), publish on 127.0.0.1 and use port 7777.
DirectNetworkOptions - The event handler logs network state changes for debugging purposes.
OnNetworkStateChanged - The event handler provides a place to respond to errors if starting the network fails.
OnNetworkStartFailed
- By omitting the call to
-
Client():
JoinSessionAsClient- The line joins the session using the provided join code.
var session = await MultiplayerService.Instance.JoinSessionByCodeAsync(sessionJoinCode); - After joining, the current network state is logged.
- The event handler ensures that clients get notified via console logs whenever the underlying network state changes.
OnNetworkStateChanged
- The line