Skip to content

Handle host migration in Mirror

Mirror’s transport stores a pending promotion, but your game must start the new host and reconnect the other clients. Before adding the role change, plan how to restore the game’s state. Starting a Mirror host creates a new game session; the relay does not transfer the former host’s objects or match state.

  1. Subscribe to OnHostPromotionReceived before starting the client.
  2. In the callback, record that the player should become the host. Do not stop the client there. The transport has sent its acknowledgement, but stopping immediately can prevent delivery.
  3. Let the relay disconnect the client. Mirror processes the disconnect and shuts down its client session.
  4. Wait until NetworkClient.active and NetworkServer.active are both false, then call NetworkManager.StartHost() or StartServer().

The next server start uses the pending claim automatically and consumes it, even if the relay later rejects it. Do not start another client session before claiming: that discards the promotion. Complete the transition within 10 seconds of the relay issuing the claim.

The following component schedules the role change outside the transport callback. Attach it to an object that remains active through client shutdown, and assign the manager and transport in the Inspector:

using BlitzRelay.Mirror;
using Mirror;
using UnityEngine;
public sealed class MirrorHostMigration : MonoBehaviour
{
[SerializeField] private NetworkManager networkManager;
[SerializeField] private BlitzRelayTransport transport;
private bool startHostPending;
private float promotionDeadline;
private void OnEnable()
{
transport.OnHostPromotionReceived += HandlePromotion;
}
private void OnDisable()
{
transport.OnHostPromotionReceived -= HandlePromotion;
}
private void HandlePromotion(HostPromotion promotion)
{
promotionDeadline = Time.realtimeSinceStartup + 10f;
startHostPending = true;
}
private void Update()
{
if (!startHostPending) return;
if (Time.realtimeSinceStartup >= promotionDeadline)
{
startHostPending = false;
transport.ClearPendingHostPromotion();
Debug.LogError("Relay host promotion timed out.");
return;
}
if (NetworkClient.active || NetworkServer.active) return;
startHostPending = false;
if (transport.HasPendingHostPromotion)
{
networkManager.StartHost();
}
}
}

This example changes the framework role only. Add your game’s state restoration and keep the host-failure handler from the setup guide. The local timer does not extend the relay’s deadline. An InvalidHostClaim response still means the promotion failed.

If the player declines promotion or abandons the room, cancel the scheduled start and call ClearPendingHostPromotion().

Keep the other clients connected to the relay while they wait for a replacement host. After OnRelayHostAvailabilityChanged(true) reports recovery from an unavailable host, schedule the following work outside the callback:

  1. Call NetworkManager.StopClient().
  2. Wait until NetworkClient.active is false.
  3. Keep the same relay settings and room code, then call NetworkManager.StartClient().

Do this only for clients that were not promoted. Track the period without a host so that the initial true notification does not start a reconnection loop. Clients waiting for a new persistent room’s first host need the same reconnection after that host becomes available.

Wait for Mirror authentication, scene loading, and your game’s state synchronisation before allowing play to resume. Connection IDs can change after reconnection; do not use them as persistent player identities.

Test with a persistent room and at least two players. Stop the active host, confirm that another player claims the same room, and confirm that the remaining clients rejoin. On relay 1.4.0 or later, repeat the test with host removal through the API. The removed host must end its session while the other players complete migration.