Game Server Hosting (Multiplay) SDK for Unity

Note: The content on this page pertains to all versions of Multiplay, including Game Server Hosting (Multiplay) and Managed Game Server Hosting (Clanforge).

The Game Server Hosting SDK for Unity has all the functionality necessary to leverage Game Server Hosting scaling and game server services in your game. Unity.Services.Multiplay is the primary namespace for interacting with the Multiplay service.

Note: Refer to Get started with Game Server Hosting and the integration requirements before continuing.

Requirements and limitations

The Game Server Hosting SDK for Unity works with Unity Editor version 2020.3 and later.

Warning: There's a known issue with Unity Editor version 2022 that prevents the SDK from working. If you use version 2022, ensure you use version 2022.2.3f1 or later.

Initialize the SDK

Use the Instance method to create a singleton of the IMultiplayService. You can use the singleton to interact with the Game Server Hosting API.

async void Example_InitSDK()
{
	try
	{
		await UnityServices.InitializeAsync();
	}
	catch (Exception e)
	{
		Debug.Log(e);
	}
}

Configure the game server

The ServerConfig class represents a game server configuration, and allows you to create a ServerConfig instance for the current game session.

Use the ServerConfig method (within the ServerConfig class) to create a ServerConfig instance for the current game session.

ParameterTypeDescription
serverIdlongThe server ID.
allocationIdstringThe allocation ID.
queryPortushortThe Server Query Protocol port number.
portushortThe connection port for the game session. This is the port number game clients can use to connect to the game session.
serverLogDirectorystringThe directory in which the game server saves log files.

The following code example shows how to use the ServerConfig method to log information about a game server, such as the server ID, allocation ID, port number, query port number, and server log directory.

using System.Collections;
using System.Collections.Generic;
using Unity.Services.Multiplay;
using UnityEngine;

public class Example_ServerConfiguration
{
	/// <summary>
	/// A simple example of accessing each of the server config's fields and printing them to the debug console.
	/// </summary>
	public static void LogServerConfig()
	{
		var serverConfig = MultiplayService.Instance.ServerConfig;
		Debug.Log($"Server ID[{serverConfig.ServerId}]");
		Debug.Log($"AllocationID[{serverConfig.AllocationId}]");
		Debug.Log($"Port[{serverConfig.Port}]");
		Debug.Log($"QueryPort[{serverConfig.QueryPort}");
		Debug.Log($"LogDirectory[{serverConfig.ServerLogDirectory}]");
	}
}

Ready the game server

Use the ReadyServerForPlayersAsync method to let Game Server Hosting know a game server is ready to receive players. Refer to Game server readiness.

using System.Threading.Tasks;
using Unity.Services.Multiplay;

/// <summary>
/// Ready the server. This is to indicate that the server is ready to accept players.
/// Readiness is the server's way of saying it's ready for players to join the server.
/// You must wait until you have been Allocated before you can call ReadyServerForPlayersAsync.
/// </summary>
private async void Example_ReadyingServer()
{
	// After the server is back to a blank slate and ready to accept new players
	await MultiplayService.Instance.ReadyServerForPlayersAsync();
}

Unready the game server

Use the UnreadyServerAsync method to let Game Server Hosting know that a game server is no longer ready to receive players. Refer to Game server readiness.

using System.Threading.Tasks;
using Unity.Services.Multiplay;

/// <summary>
/// Unready the server. This is to indicate that the server is in some condition which means it can't accept players.
/// For example, after a game has ended and you need to reset the server to prepare for a new match.
/// </summary>
private async void Example_UnreadyingServer()
{
	// The match has ended and players are disconnected from the server
	await MultiplayService.Instance.UnreadyServerAsync();
}

Start server query handler

Use the StartServerQueryHandlerAsync method to connect to the game server’s SQP implementation with the provided parameters.

ParameterTypeDescription
maxPlayersushortThe maximum number of players on the server.
serverNamestringThe name for the server.
gameTypestringThe name or identifier of the game type the server is running.
buildIdstringThe version of the game.
mapstringThe map or world the server is running for the game.
portushortThe port number of the game server that the game client can use to connect.

Game Server Hosting uses the StartServerQueryHandlerAsyncparameters to initialize the server query handler.

After you initialize the server query handler, you can use the IServerCheckManager instance provided by this call to update the values at any time. You must call UpdateServerCheck() for the changes to take effect. Call UpdateServerCheck() when game server variables change. Refer to SQP for more information.

You should call UpdateServerCheck() often enough to ensure you send up-to-date data back to Game Server Hosting when the query request happens every 60 seconds.

One of the best ways to do so is to call it in the Update loop. But you can also call it when specific game events occur, such as a player joining, a player leaving, or a game match starting.

Note: The currentPlayers field always starts at 0. You must update this value each time a player connects to (or disconnects from) the game server.

The following example shows how to start the server query handler.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Unity.Services.Multiplay;

/// <summary>
/// An example of how to use SQP from the server using the Multiplay SDK.
/// The ServerQueryHandler reports the given information to the Multiplay Service.
/// </summary>
public class Example_ServerQueryHandler : MonoBehaviour
{
	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";

	public ushort currentPlayers;

	private IServerQueryHandler m_ServerQueryHandler;

	private async void Start()
	{
		m_ServerQueryHandler = await MultiplayService.Instance.StartServerQueryHandlerAsync(k_DefaultMaxPlayers, k_DefaultServerName, k_DefaultGameType, k_DefaultBuildId, k_DefaultMap);
	}

	private void Update()
	{
		m_ServerQueryHandler.UpdateServerCheck();
	}

	public void ChangeQueryResponseValues(ushort maxPlayers, string serverName, string gameType, string buildId)
	{
		m_ServerQueryHandler.MaxPlayers = maxPlayers;
		m_ServerQueryHandler.ServerName = serverName;
		m_ServerQueryHandler.GameType = gameType;
		m_ServerQueryHandler.BuildId = buildId;
	}

	public void PlayerCountChanged(ushort newPlayerCount)
	{
		m_ServerQueryHandler.CurrentPlayers = newPlayerCount;
	}
}

Subscribe to server events

Use the SubscribeToServerEventsAsync method to subscribe to server event callbacks for a game server.

The following example shows how to subscribe to and handle game server event callbacks, including OnAllocate, OnDeallocate, and OnError.

using System;
using System.Collections;
using System.Collections.Generic;
using Unity.Services.Multiplay;
using UnityEngine;

/// <summary>
/// An example of how to access and react to multiplay server events.
/// </summary>
public class Example_ServerEvents : MonoBehaviour
{
	private MultiplayEventCallbacks m_MultiplayEventCallbacks;
	private IServerEvents m_ServerEvents;

	/// <summary>
	/// This should be done early in the server's lifecycle, as you'll want to receive events as soon as possible.
	/// </summary>
	private async void Start()
	{
		// We must first prepare our callbacks like so:
		m_MultiplayEventCallbacks = new MultiplayEventCallbacks();
		m_MultiplayEventCallbacks.Allocate += OnAllocate;
		m_MultiplayEventCallbacks.Deallocate += OnDeallocate;
		m_MultiplayEventCallbacks.Error += OnError;
		m_MultiplayEventCallbacks.SubscriptionStateChanged += OnSubscriptionStateChanged;

		// We must then subscribe.
		m_ServerEvents = await MultiplayService.Instance.SubscribeToServerEventsAsync(m_MultiplayEventCallbacks);
	}

// Handle Multiplay events.

}

Handle Game Server Hosting events

The MultiplayEventCallbacks class provides callbacks for responding to Game Server Hosting events, such as allocations, deallocations, errors, and game server state changes.

The following code example shows how to respond to event callbacks, such as OnAllocate, OnDeallocate, and OnError.

using System;
using System.Collections;
using System.Collections.Generic;
using Unity.Services.Multiplay;
using UnityEngine;

/// <summary>
/// An example of how to access and react to multiplay server events.
/// </summary>
public class Example_ServerEvents : MonoBehaviour
{
	private MultiplayEventCallbacks m_MultiplayEventCallbacks;
	private IServerEvents m_ServerEvents;

	/// <summary>
	/// This should be done early in the server's lifecycle, as you'll want to receive events as soon as possible.
	/// </summary>
	private async void Start()
	{
		// We must first prepare our callbacks like so:
		m_MultiplayEventCallbacks = new MultiplayEventCallbacks();
		m_MultiplayEventCallbacks.Allocate += OnAllocate;
		m_MultiplayEventCallbacks.Deallocate += OnDeallocate;
		m_MultiplayEventCallbacks.Error += OnError;
		m_MultiplayEventCallbacks.SubscriptionStateChanged += OnSubscriptionStateChanged;

		// We must then subscribe.
		m_ServerEvents = await MultiplayService.Instance.SubscribeToServerEventsAsync(m_MultiplayEventCallbacks);
	}

	/// <summary>
	/// Handler for receiving the allocation multiplay server event.
	/// </summary>
	/// <param name="allocation">The allocation received from the event.</param>
	private void OnAllocate(MultiplayAllocation allocation)
	{
		// Here is where you handle the allocation.
		// This is highly dependent on your game, however this would typically be some sort of setup process.
		// Whereby, you spawn NPCs, setup the map, log to a file, or otherwise prepare for players.
		// After you the allocation has been handled, you can then call ReadyServerForPlayersAsync()!
	}

	/// <summary>
	/// Handler for receiving the deallocation multiplay server event.
	/// </summary>
	/// <param name="deallocation">The deallocation received from the event.</param>
	private void OnDeallocate(MultiplayDeallocation deallocation)
	{
		// Here is where you handle the deallocation.
		// This is highly dependent on your game, however this would typically be some sort of teardown process.
		// You might want to deactivate unnecessary NPCs, log to a file, or perform any other cleanup actions.
	}

	/// <summary>
	/// Handler for receiving the error multiplay server event.
	/// </summary>
	/// <param name="error">The error received from the event.</param>
	private void OnError(MultiplayError error)
	{
		// Here is where you handle the error.
		// This is highly dependent on your game. You can inspect the error by accessing the error.Reason and error.Detail fields.
		// You can change on the error.Reason field, log the error, or otherwise handle it as you need to.
	}

	/// <summary>
	///
	/// </summary>
	/// <param name="state"></param>
	private void OnSubscriptionStateChanged(MultiplayServerSubscriptionState state)
	{
		switch (state)
		{
			case MultiplayServerSubscriptionState.Unsubscribed: /* The Server Events subscription has been unsubscribed from. */ break;
			case MultiplayServerSubscriptionState.Synced: /* The Server Events subscription is up to date and active. */ break;
			case MultiplayServerSubscriptionState.Unsynced: /* The Server Events subscription has fallen out of sync, the subscription tries to automatically recover. */ break;
			case MultiplayServerSubscriptionState.Error: /* The Server Events subscription has fallen into an errored state and won't recover automatically. */ break;
			case MultiplayServerSubscriptionState.Subscribing: /* The Server Events subscription is trying to sync. */ break;
		}
	}
}

Allocate

public event Action<MultiplayAllocation> Allocate;

Use the Allocate callback to respond to a MultiplayAllocation event.

Deallocate

public event Action<MultiplayDeallocation> Deallocate;

Use the Deallocate callback to respond to a MultiplayDeallocation event.

Error

public event Action<MultiplayError> Error;

Use the Error callback to respond to a MultiplayError event.

SubscriptionStateChange

public event Action<MultiplayServerSubscriptionState> SubscriptionStateChanged;

Use the SubscriptionStateChanged callback to respond to a MultiplayServerSubscriptionState event.

Deploying resources with Unity Editor

The Multiplay Authoring module (installed with the Multiplay package) allows you to optionally author and modify resources directly within the Unity Editor. You can then upload resources from the Unity Editor to the Dashboard by using the Deployment package.

Multiplay configurations existing in the Unity Editor allow users to treat their source control as the single source of truth (instead of the version in the cloud), simplifying actions such as rollbacks, bisection, and other common operations.

Prerequisites

To use Multiplay in the Unity Editor, you must first install the com.unity.services.multiplay SDK and link your Unity Gaming Services project to the Unity Editor.

Link your Unity Gaming Services project with the Unity Editor. You can find your UGS project ID in the Unity Dashboard.

  1. In Unity Editor, select Edit > Project Settings > Services.

  2. Link your project.

  • If your project doesn't have a Unity project ID:
1.  Select **Create a Unity Project ID** > **Organizations**, then select an organization from the dropdown menu.
2.  Select **Create project ID**.
  • If you have an existing Unity project ID:
1.  Select **Use an existing Unity project ID**.
2.  Select an organization and a project from the dropdown menus.
3.  Select **Link project ID**.

Your Unity Project ID appears, and the project is now linked to Unity services. You can also access your project ID in a Unity Editor script using UnityEditor.CloudProjectSettings.projectId.

Install required packages

To create Multiplay configurations within the Editor, you must install the following packages:

  • Deployment
  • Multiplay (com.unity.services.multiplay@1.1.0 or greater)

Refer to Unity - Manual: Package Manager window to familiarize yourself with the Unity Package Manager interface.

To install these packages and add them to your list of available packages:

  1. From the Unity Editor’s Package Manager window, select + (add) > Add package by name….
  2. Enter com.unity.services.deployment.
  3. Select Add.
  4. Repeat these steps for com.unity.services.multiplay.

Authoring within Unity Editor

The Multiplay Authoring module allows you to create, edit, and deploy Multiplay configurations directly within the Unity Editor.

Create a configuration

Follow these steps to create an Multiplay configuration using the Multiplay Authoring module:

  1. In the Unity Editor, right-click in the Project window, then select Create > Multiplay Config.
  2. Give the resource file a name.
  3. Press Enter.

The new configuration is now visible in the Project window, and in the Deployment window, accessible by selecting Services > Deployment.

Edit a configuration

There is currently one method to edit an existing configuration:

  • In the Project tab, double-click the existing resource, then choose any text editor to edit the configuration.

Resource file content

The deployment window finds resources and assigns their type according to their file extension.

The configuration uses the yaml format to describe its contents and the .gsh file extension.

Example for new_multiplay_config.gsh:

version: 1.0
builds:
  my build: # replace with the name for your build
    executableName: Build.x86_64 # the name of your build executable
    buildPath: Builds/Multiplay # the location of the build files
buildConfigurations:
  my build configuration: # replace with the name for your build configuration
    build: my build # replace with the name for your build
    queryType: sqp # sqp or a2s, delete if you do not have logs to query
    binaryPath: Build.x86_64 # the name of your build executable
    commandLine: -port $$port$$ -queryport $$query_port$$ -log $$log_dir$$/Engine.log # launch parameters for your server
    variables: {}
    cores: 1 # number of cores per server
    speedMhz: 750 # launch parameters for your server
    memoryMiB: 800 # launch parameters for your server
fleets:
  my fleet: # replace with the name for your fleet
    buildConfigurations:
      - my build configuration # replace with the names of your build configuration
    regions:
      North America: # North America, Europe, Asia, South America, Australia
        minAvailable: 0 # minimum number of servers running in the region
        maxServers: 1 # maximum number of servers running in the region

The configuration describes 3 components within the file:

Deploy a resource

You can deploy a Multiplay configuration through the Deployment window. Refer to the Deployment package manual for more information.

Some configurations have dependencies on other resources,such as build configurations being dependent on the build itself.

When deploying, Builds will deploy first, then the Build Configurations, then the Fleets. A failure at one point in the chain will halt deployment for the configurations that depend on it.

Deployment window

The Deployment window is a core feature of the Deployment package. It allows all services to have a single cohesive interface for deployment needs, and allows you to upload cloud assets to their respective cloud services.

Refer to the Deployment package manual for more information.