Version: 2019.4
言語: 日本語
ネットワーク のクライアントとサーバー
Network Discovery

ホストマイグレーション

ノート: UNet は非推奨となり、今後 Unity から削除される予定です。新しいシステムが開発中です。詳細は ブログFAQ を参照してください。

専用サーバーなしのマルチプレイヤーネットワークゲームでは、ゲームインスタンスの 1 つがホスト、つまりゲーム権限の中心として機能します。このプレイヤーのゲームがサーバーおよび「ローカルクライアント」の働きをします。一方、他のプレイヤーは、それぞれ「リモートクライアント」を実行します。詳しくは ネットワークシステムの概念 を参照してください。

ホストがゲームとの接続を切ると、ゲームを続行することができません。ホストが切断するよくある理由は、ホストプレイヤーのゲーム離脱、ホストの処理のクラッシュ、ホストのマシンのシャットダウン、ホストのネットワーク接続の遮断などです。

Host Migration 機能を使用するとリモートクライアントの 1 つを新しいホストにすることができるので、マルチプレイヤーゲームを継続させることが可能になります。

仕組み

マルチプレイヤーゲームを実行中に Host Migration が有効になっている場合、Unity はゲーム内のすべてのピア (ホストとすべてのクライアントを含むプレイヤー) のアドレスを他のすべてのピアに知らせます。ホストの接続が失われると、ピアのうち 1 つが新しいホストになり、その他のピアが新しいホストに接続してゲームが続行します。

新しい Network Migration Manager コンポーネントは、Unity Networking HLAPI を利用しています。これによって、元のホストが失われても新しいホストが設定されてゲームが継続可能になります。以下のスクリーンショットは、インスペクターウィンドウの Network Migration Manager にマイグレーション状態が表示されている様子です。

Network Migration Manager コンポーネント
Network Migration Manager コンポーネント

Network Migration Manager は Network Manager HUD に似た基本的なユーザーインターフェースを提供します。このユーザーインターフェースは、ゲーム開発中のテストやプロトタイプのためのものです。ゲームのリリース前に、ホストマイグレーションのためのカスタムのユーザーインターフェースや、ユーザーによる入力なしで新しいホストを自動的に選択するなどのカスタムのロジックを実装する必要があります。

Network Migration Manager のプロトタイプ HUD
Network Migration Manager のプロトタイプ HUD

ホストの接続が切れたりホストがゲームを離脱したためにマイグレーションが行われた場合でも、古いホストは、新しいホストのクライアントとしてゲームに再参加できます。

ホストのマイグレーションが行われる際、シーン内のすべてのネットワーク オブジェクトの SyncVarsSyncLists の状態がシーン内のすべてのネットワーク化されたゲームオブジェクトで維持されます。これは、オブジェクトのシリアル化されたカスタムデータについても同様です。

ホストの接続が失われると、ゲーム中のすべてのプレイヤーゲームオブジェクトが無効になります。別のクライアントが新しいホストの新しいゲームに再参加すると、そのクライアントに対応するプレイヤーがホスト上で再び有効化され、他のクライアント上でオブジェクトが再生成されます。したがって、どのプレイヤーの状態データも、ホストマイグレーション中に失われることはありません。

ノート: ホストマイグレーション中に保持されるのは、クライアントにとって利用可能なデータのみです。サーバー上にしかないデータが存在する場合、新しくホストになるクライアントはそのデータを利用することができません。ホストマイグレーションが行われた後は、ホスト上のデータは、それが SyncVars か SyncLists にある場合にのみ利用可能です。

クライアントが新しくホストになると、コールバック関数 OnStartServer がすべてのネットワーク化されたゲームオブジェクトに対して呼び出されます。新しいホスト上で、Network Migration Manager が関数 BecomeNewHost を使用して、現在の ClientScene の状態を元に、ネットワーク化されたサーバーシーンを構築します。

ホストマイグレーションが可能なゲームでは、ピアはconnectionId によってサーバー上で識別されます。クライアントがゲームの新しいホストに再接続すると、この connectionId が新しいホストに渡され、ホストはreconnectId に基づいてこのクライアントを古いホストに接続していたクライアントにマッチします。

ノンプレイヤーゲームオブジェクト

ホストマイグレーションには、クライアント権限を持つノンプレイヤーゲームオブジェクトの処理も含まれます。プレイヤーゲームオブジェクト同様、クライアントが持つノンプレイヤーゲームオブジェクトも、いったん無効にされたうえで再度有効にされます。

ピアの識別

ホストの接続が失われるまでは、すべてのピアはホストに接続されています。それぞれのピアが固有の connectionId をホスト上に持っています。この Id はホストマイグレーションにおいては oldConnectionId と呼ばれます。

Network Migration Manager が新しいホストを選択し、ピアがそのホストに再接続されると、各ピアはそれぞれのピアを識別するための oldConnectionId を送信します。これによって新しいホストは、再接続したクライアントを、対応するプレイヤーゲームオブジェクトとマッチすることができます。

古いホストは特別な oldConnectionId である 0 を使用し再接続します - なぜなら、以前はこれ自体がホストであったため、以前のホストへの接続がないからです。このために定数 ClientScene.ReconnectIdHost があります。

Network Migration Manager のビルトインのユーザーインターフェースを使用する場合、oldConnectionId は自動で設定されます。これは NetworkMigrationManager.Reset あるいは ClientScene.SetReconnectId を使用して手動で設定することも可能です。

ホストマイグレーションの流れ

  • マシン A が、ホストマイグレーションが可能なゲーム 1 をホストします

  • マシン B がクライアントを開始し、ゲーム 1 に参加します

    • マシン B がピアの情報を受け取ります (マシン A–0、自身 (マシン B)–1)
  • マシン C がクライアントを開始し、ゲーム 1 に参加します

    • マシン C がピアの情報を受け取ります (マシン A–0、マシン B–1、自身 (マシン C)–2)
  • マシン A がゲーム 1 への接続を切り、そのため、ホストが切断されます

  • マシン B のホストへの接続が切断されます

    • マシン B のコールバック関数がクライアント上の MigrationManager で呼び出されます

    • マシン B のプレイヤーオブジェクトがすべてのプレイヤーに対して無効になります

    • マシン B はオンラインのシーンに留まります

  • マシン B がユーティリティー関数を使用して新しいホストを選択し、マシン B 自身を選びます

    • マシン B が BecomeNewHost() を呼び出します

    • マシン B がリッスンを開始します

    • マシン B 自体で、マシン B のプレイヤーゲームオブジェクトが再アクティベートされます

    • マシン B のプレイヤーが以前の状態のままゲームに戻ります

  • マシン C のホストへの接続が切断されます

    • マシン C のコールバック関数がクライアント上の MigrationManager で呼び出されます

    • マシン C のプレイヤーオブジェクトがすべてのプレイヤーに対して無効になります

    • マシン C はオンラインのシーンに留まります

  • マシン C がユーティリティー関数を使用して新しいホストを選択し、マシン B を選びます

    • マシン C が新しいホストに再接続します
  • マシン B が マシン C からの接続を受け入れます

    • マシン C が AddPlayer メッセージではなく、oldConnectionId を持つ再接続メッセージを送信します

    • サーバー上の MigrationManager でコールバック関数が呼び出されます

    • マシン B が oldConnectionId を使ってそのプレイヤーの無効になったプレイヤーゲームオブジェクトを検索し、ReconnectPlayerForConnection() を使って再び加えます

    • プレイヤーゲームオブジェクトはマシン C のために再スポーンされます

    • マシン C のプレイヤーが以前の状態のままゲームに戻ります

  • マシン A がゲームに戻ります (古いホスト)

    • マシン A がユーティリティー関数を使用して新しいホストを選択し、マシン B を選びます

    • マシン A がマシン B に再接続します

  • マシン B が マシン A からの接続を受け入れます

  • マシン A は 0 の oldConnectionId を持つ再接続メッセージを送信します

    • サーバー (マシン B) 上の MigrationManager でコールバック関数が呼び出されます

    • マシン B が oldConnectionId を使ってそのプレイヤーの無効になったプレイヤーゲームオブジェクトを検索し、ReconnectPlayerForConnection() を使って再び加えます

    • プレイヤーゲームオブジェクトはマシン A のために再スポーンされます

    • マシン 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)

制約

ホストマイグレーションが適切に行われるためには、ゲームオブジェクトの Network Manager コンポーネントで Auto Create Player を有効にします。ホストが接続を断つとき、サーバー (ホスト) だけに存在するデータは失われます。ゲームがホストマイグレーションを正しく行うためには、重要なデータはサーバーに秘密裏に保存するのではなく、クライアントにも配信する必要があります。

これは、ゲームが直接接続を使用している場合に該当します。マッチメーカーやリレーサーバーを使用している場合には、追加の作業が必要です。

ネットワーク のクライアントとサーバー
Network Discovery