専用サーバーなしのマルチプレイヤー・ネットワークゲームでは、ゲーム中のピアのひとつがゲーム権限の中枢として機能します。このピアのことをホストと呼びます。このピアがサーバーと「ローカルクライアント」を実行するのに対し、その他のピアはそれぞれが「リモートクライアント」を実行します。
ホストが失われると、ゲームを続行することができません。ホストが失われるのは、プレイヤーがゲームを抜けた場合、ホストの処理が停止あるいはクラッシュした場合、ホストのマシンがシャットダウンされた場合、ホストのネットワーク接続が切れた場合などです。
「ホストマイグレーション」機能を使用すると、リモートクライアントのひとつを新しいホストにすることができるので、マルチプレイヤーゲームを継続させることが可能になります。
ホストマイグレーションが有効になっている場合、マルチプレイヤーゲームを実行中に、ピアのアドレスがゲーム中のピアに分配されます。ホストが失われると、ピアのひとつが新しいホストになり、その他のピアが新しいホストに接続されて、ゲームが継続されます。
新しい NetworkMigrationManager コンポーネントは、Unity Networking HLAPI を使用するマルチプレイヤーゲームにドロップすることが可能です。これによって、元々のホストが失われても新しいホストが設定されてゲームが継続可能になります。以下はエディター インスペクターの NetworkMigrationManager のスクリーンショットです。ここに現在のマイグレーションの状態が表示されます。
NetworkMigrationManager によって、NetworkManagerHUD に似たシンプルなユーザーインターフェースが提供されます。このユーザーインターフェースはテストやプロトタイピングのためのものです。実際のゲームでのホストマイグレーションには、カスタムのユーザーインターフェースが実装され、また多くの場合、カスタムのロジック(ユーザーによる入力なしで新しいホストを自動的に選択するなど)も実装されます。
古いホストの接続が切れたりゲームを抜けたりしたためにマイグレーションが行われた場合でも、古いホストは、新しいホストのクライアントとしてゲームに再参加できます。
ホストマイグレーションが行われる際、シーン内のすべてのネットワーク オブジェクトの SyncVar と SyncList の状態が維持されます。これは、オブジェクトの、シリアライズされたカスタムデータについても同様です。
ホストが失われると、ゲーム中のすべてのプレイヤーオブジェクトが無効になります。別のクライアントが新しいホストで新しいゲームに再参加すると、そのクライアントに対応するプレイヤーがホスト上で再び有効化され、他のクライアント上でオブジェクトが再生成されます。したがって、どのプレイヤーの状態データも、マイグレーション中に失われることはありません。
(注) ホストマイグレーション中に保持されるのは、クライアントによって利用可能なデータのみです。サーバー上にしかないデータが存在する場合、新しくホストになるクライアントはそのデータを利用することができません。したがって、SyncVar や SyncList に保存されていないホスト上のデータは、ホストマイグレーションが行われた後には利用不可能になります。
クライアントが新しくホストになると、コールバック関数 OnStartServer がすべてのネットワーク オブジェクトに実行されます。
新しいホスト上で、NetworkMigrationManager が関数 BecomeNewHost を使用して、現在の ClientSceneto の状態を元に、ネットワーク化されたサーバーシーンを構築します。
ホストマイグレーションが有効になったピアは、その connectionId
によってサーバー上で識別されます。クライアントがゲームの新しいホストに再接続されると、この connectionId が新しいホストに渡され、古いホストに接続されていたクライアントにこのクライアントがマッチされます。この Id は ClientScene で “reconnectId” として設定されます。
ホストマイグレーションには、クライアント権限を持った非プレイヤー オブジェクトの処理も含まれます。プレイヤー オブジェクト同様、各クライアントが持つオブジェクトが、いったん無効化されたうえで再有効化されます。
ホストが失われるまでは、すべてのピアはホストに接続されています。それぞれのピアが固有の connectionId をホスト上に持っています。この Id はホストマイグレーションにおいては “oldConnectionId” と呼ばれます。
新しいホストが選択されてピアがそのホストに再接続されると、各ピアによって “oldConnectionId” が提供されます。これはそれぞれのピアを識別するためのものです。これによって新しいホストは、再接続したクライアントを、対応するプレイヤーオブジェクトとマッチさせることができるようになります。
古いホストの使用は 0 の特別な oldConnectionId に再接続します - 古いホストへの接続を持っていなかったので、ホストは古いホストです。このために ClientScene.ReconnectIdHost があります。
ビルトインのユーザーインターフェースを使用する場合、oldConnectionId は自動で設定されます。これは NetworkMigrationManager.Reset あるいは ClientScene.SetReconnectId を使用して手動で設定することも可能です。
マシン A が、ホストマイグレーションが有効になったゲームをホストする
マシン A が失われる(したがってホストが失われる)
マシン B が マシン A からの接続を受け入れる
NetworkHostMigrationManager のコールバック関数
//ホストへの接続を失った後に、クライアント上で呼び出されます。シーンを変更するかを制御します。
protected virtual void OnClientDisconnectedFromHost(
NetworkConnection conn,
out SceneChangeOption sceneChange)
// ホストへの接続を失った後に、ホスト上で呼び出されます。ホストはシーンを変更する必要があります。
protected virtual void OnServerHostShutdown()
//古いホストのクライアントがプレイヤーに再接続するとき、新しい ホスト (サーバー) 上で呼び出されます。
protected virtual void OnServerReconnectPlayer(
NetworkConnection newConnection,
GameObject oldPlayer,
int oldConnectionId,
short playerControllerId)
// 古いホストのクライアントがプレイヤーに再接続するとき、新しい ホスト (サーバー) 上で呼び出されます。
protected virtual void OnServerReconnectPlayer(
NetworkConnection newConnection,
GameObject oldPlayer,
int oldConnectionId,
short playerControllerId,
NetworkReader extraMessageReader)
// 古いホストのクライアントがプレイヤー以外のオブジェクトに再接続するとき、新しい ホスト (サーバー) 上で呼び出されます。
protected virtual void OnServerReconnectObject(
NetworkConnection newConnection,
GameObject oldObject,
int oldConnectionId)
// ピアが更新されるときに、ホストとクライアントの両方で呼び出されます。
protected virtual void OnPeersUpdated(
PeerListMessage peers)
//新しいホストを設定するために、ホストへの接続を失った後に、クライアント上のデフォルト UI によって呼び出されるユーティリティ関数
public virtual bool FindNewHost(
out NetworkSystem.PeerInfoMessage newHostInfo,
out bool youAreNewHost)
//プレイヤー以外のオブジェクトの許可が変わるときに呼び出されます
protected virtual void OnAuthorityUpdated(
GameObject go,
int connectionId,
bool authorityState)
サーバー(ホスト)のみに存在していたデータは、ホストの接続が切れると失われます。ホストマイグレーションが正常に実行されるためには、重要なデータを(サーバー上だけに保管するのではなく)クライアントに配信する必要があります。
上記は、ゲームが直接接続を使用している場合に当てはまる説明です。マッチメーカーやリレーサーバーを使用している場合には、追加の作業が必要となります。