Multiplay Hosting support

Multiplayer Services sessions are compatible with Multiplay Hosting. The Multiplayer Services package provides out-of-the-box support for Multiplay Hosting's Server query protocol.

The easiest way to allocate a server on Multiplay Hosting is to use and configure it through Unity Matchmaker, which automatically allocates the game server. Unity's Multiplayer Services package helps with configuring the required hooks in Multiplay Hosting.

The following code demonstrates how to start an SQP-backed session on the server:

#if UNITY_SERVER || ENABLE_UCS_SERVER    

    // Please refer to the linked Server Query Protocol documentation.
    private const ushort k_DefaultMaxPlayers = 10;
    private const string k_DefaultServerName = "MyServerExample";
    private const string k_DefaultGameType = "MyGameType";
    private const string k_DefaultBuildId = "MyBuildId";
    private const string k_DefaultMap = "MyMap";

    IMultiplaySessionManager m_SessionManager;

    async Task ConnectToMultiplay()
    {
        if (UnityServices.Instance.GetMultiplayerService() != null)
        {
            // Authenticate
            await ServerAuthenticationService.Instance.SignInFromServerAsync();
            var token = ServerAuthenticationService.Instance.AccessToken;

            // Callbacks should be used to ensure proper state of the server allocation.
            // Awaiting the StartMultiplaySessionManagerAsync won't guarantee proper state.
            var callbacks = new MultiplaySessionManagerEventCallbacks();
            callbacks.Allocated += OnServerAllocatedCallback;

            var sessionManagerOptions = new MultiplaySessionManagerOptions()
            {
                SessionOptions = new SessionOptions()
                {
                    MaxPlayers = k_DefaultMaxPlayers
                }.WithDirectNetwork(),

                // Server options are REQUIRED for the underlying SQP server
                MultiplayServerOptions = new MultiplayServerOptions(
                    serverName: k_DefaultServerName,
                    gameType: k_DefaultGameType,
                    buildId: k_DefaultBuildId,
                    map: k_DefaultMap
                ),
                Callbacks = callbacks
            };
            m_SessionManager = await MultiplayerServerService.Instance.StartMultiplaySessionManagerAsync(sessionManagerOptions);

           // Ensure that the session is only accessed after the allocation happened. 
           // Otherwise you risk the Session being in an uninitialized state.
            async void OnServerAllocatedCallback(IMultiplayAllocation obj)
            {
                var session = m_SessionManager.Session;
                await m_SessionManager.SetPlayerReadinessAsync(true);
                Debug.Log("[Multiplay] Server is ready to accept players");
            }
        }
    }
#endif

Note: When using Matchmaker, even though the maximum number of players in a match is defined on the configuration, it is necessary to set it here, as well. Make sure that the maximum number of players defined here is at least as large as the one defined on the Matchmaker.

This code automatically creates a session for players to connect to when the server becomes allocated. It should be called as soon as the server is ready to receive players.

Refer to:

Authentication

Refer to Multiplay Hosting

Server readiness

If Multiplay Hosting's Server readiness feature is enabled in the Build Configuration, it is possible to set the server as ready to receive player connections using the following code:

await sessionManager.SetPlayerReadinessAsync(true);

When using Matchmaker, if the feature is enabled, the player is only assigned to the server once the server is ready.

Backfilling

If the server was allocated with Matchmaker, it's possible to automatically request new players to join in order to backfill empty slots as a result of players leaving the session or because the match was created eagerly to minimize matchmaking time:

// Callbacks should be used to ensure proper state of the server allocation.
// Awaiting the StartMultiplaySessionManagerAsync won't guarantee proper state.
var callbacks = new MultiplaySessionManagerEventCallbacks();
callbacks.Allocated += OnServerAllocatedCallback;

var sessionManagerOptions = new MultiplaySessionManagerOptions()
{
    SessionOptions = new SessionOptions()
    {
        MaxPlayers = 2
    }.WithBackfillingConfiguration(enable: true, autoStart: true),

    MultiplayServerOptions = new MultiplayServerOptions(
        serverName: k_DefaultServerName,
        gameType: k_DefaultGameType,
        buildId: k_DefaultBuildId,
        map: k_DefaultMap
    ),
    Callbacks = callbacks
};
m_SessionManager = await MultiplayerServerService.Instance.StartMultiplaySessionManagerAsync(sessionManagerOptions);

// Ensure that the session is only accessed after the allocation happened. 
// Otherwise you risk the session being in an uninitialized state.
async void OnServerAllocatedCallback(IMultiplayAllocation obj)
{
    var session = sessionManager.Session;
}

This code starts the backfilling process as soon as Multiplay Hosting allocates the server (if the session is not full). Additionally, this code automatically starts the backfilling process when the session has one more empty slot.

Note: If MaxPlayers defined here is not equal to the one in the matchmaking configuration, backfilling does not work as expected.

It is also possible to manually start and stop the backfilling process using the following code:

var sessionManager = await MultiplayerServerService.Instance. StartMultiplaySessionManagerAsync(sessionManagerOptions);

// Ensure that the session is only accessed after the allocation happened. 
// Otherwise you risk the session being in an uninitialized state.
async void OnServerAllocatedCallback(IMultiplayAllocation obj)
{
    // Start the backfilling if it is not already in progress
    await sessionManager.Session.StartBackfillingAsync(); 
    
    /// Stop the backfilling
    await sessionManager.Session.StopBackfillingAsync(); 
}

Starting and stopping the backfilling of a session can be useful if certain times are not appropriate for players to be joining (for example, if the session is about to end, or if a cinematic is in progress).

Refer to WithBackfillingConfiguration() for more information on the backfilling configuration.

Build configuration launch parameters

The default launch parameters for games using sessions are the following:

-nographics -batchmode -port $$port$$ -logFile $$log_dir$$/Engine.log -queryPort $$query_port$$ -queryType $$query_type$$

Refer to Multiplay Hosting's Launch parameters for more information.