このページは編集中です。更新が保留になっている可能性があります。

ホストマイグレーション API

概要

Photon Fusionは様々なアーキテクチャに対応しています。そのうちの1つはClient Hostedトポロジで、FusionではHostModeと呼んでいます。HostModeとはゲームセッション内のクライアントがゲームの ホスト としての役目を追うものです。クライアントホストはローカルコンピュータから新しくゲームセッションを作成して提供を行い、そのマシンをゲームセッションのサーバーとして他のプレイヤーのプレイ接続を許可します。

Fusionは、クライアントとホストの間の接続全てを確立するのに必要な全てを取り扱うNATパンチスルーアルゴリズムを導入しています。そのためポート転送やファイアウォールルールの設定が必要ありません。これによりプレイヤーホストのゲーム開発が簡単になっています。

主なメリットは主なデメリットでもあります。インフラストラクチャのコントロールがしづらいということです。以下の様な場合にはゲームセッションの品質が落ちたり、停止したりします。

  1. 家庭用ネットワーク上のトラフィックの品質にはばらつきがある場合。これはゲームホストのインターネット接続/サブスクリプションによるもの。; and,
  2. 電源が落ちたりシャットダウンされることでホストマシンが落ちる場合(システムアップデートまたはプレイヤーの手による)

この双方のポイントが、特にゲームセッションが停止された直後において、プレイヤー体験を悪化させる可能性があります。HostModeのFusionゲームが稼働するのがゲームサーバーが存在する場合のみであるためです。

この問題を解決するため、Fusionはデベロッパーが統合できるHost Migration API/システム を搭載しています。Fusionのホストマイグレーション機能を活用するとゲームセッション内の他のクライアントピアにゲームのホストを引き継ぐことができ、ゲームせしょんを引き続き行うことができます。これはゲーム体験全体にプラスに働き、専用サーバーでのServerModeのヘッドレスインスタンスを稼働させる野に必要なインフラストラクチャの実質的な代替案となります。

備考: 実装例はFusion Host Migration Sampleでご覧いただけます。

トップに戻る

ホストマイグレーション

ホストマイグレーションの事項には、いくつかの前提条件が必要となります。

  1. Fusionの開始時、ピアの1人がホスト(同一マシンでサーバーおよびプレイヤーとなる)としてシミュレーションを開始する必要があります。これは、GameMode.Host または GameMode.AutoHostOrClientパラメータを使用して、Fusion Simulation (NetworkRunner.StartGame())を起動することで実行可能。
  2. ホストマイグレーションの有効化。ホストマイグレーションは オプション 機能のため、実装に手動作業が必要となります。デフォルトでは有効になっていません。
  3. ゲームの移行準備を行います。ホストを他のマシンに移行するのは簡単ではありませんが、Fusionではこれをできるだけシンプルにしています。このシステムは、旧ホストのゲーム状態全体にアクセスすることができ、移行プロセスに入るもの、出るものを強制するものではありません。

トップに戻る

ホストマイグレーションの有効化

ホストマイグレーションを有効にするには、Fusion > Network Project ConfigメニューからNetworkProjectConfigを開き、アセットのConfigセクションで以下の設定を確認します。

  • Enable Host Migration: ボックスにチェックを入れるとホストマイグレーションシステムが有効になります。
  • Host Migration Snapshot Interval: PhotonCloudへスナップショットを送信するための秒単位でのインターバル。適切な値はゲームのペースによって異なります。多くの場合、30秒が推奨されます。クラウドに保存されるのは最新のスナップショットのみのため、ホスト移行が必要になり最後のスナップショット間のゲームステートに変更が生じると実際のホストマイグレーションは失われます。
    Add Fusion Stats
    Host Migration Settings in the Network Project Config Asset

トップに戻る

ホストマイグレーションを実行する

ホストマイグレーションの中心となるエントリポイントはINetworkRunnerCallbacks.OnHostMigrationコールバックです。ゲームがホストマイグレーションの実行を必要とするとOnHostMigration()が起動されます。

Fusionは ホストのゲームステートを反復可能なNetworkObjectsのリストとして公開します。ここには、 ホストがゲームステートの再構築する際に、前回のものとできるだけ同様のものにするのに必要なデータが含まれます。

ホストマイグレーションのプロセスは以下の通りです。

  1. Fusion Server Plugin(Photon Cloudでのホスティング)がホストピアのセッション退出を検知すると、その他の全ピアでホストマイグレーションプロセスが起動される。この時点では、
    1. 新しいホストが選出され、;
    2. ホストから受信した、最後に保存されたゲームステートが ホストに送信される。 重要: このスナップショットが送信されるのは新ホストのみで、その他のピアには送信されない。
  2. INetworkRunnerCallbacks.OnHostMigrationコールバックが起動され、マイグレーションプロセスが開始される。
    1. 現在のFusion NetworkRunnerはまだ稼働状態のため、手動でシャットダウンする必要がある。デベロッパーは、マイグレーション自体を実行する前に必要なリセットおよび・またはセットアップを行うことができる。
    2. 新しいホストに接続してゲームを再開するために新しいFusion NetworkRunnerが作成される必要がある。旧Runnerの再使用はサポートされていない。旧ゲームについての必要な情報は全てHostMigrationTokenによって転送される。これはOnHostMigrationコールバックから取得可能。このステップは新ホストと接続中の新クライアントの双方で行われる。特定のピアで使用されるSessionNameGameModeはどちらもHostMigrationTokenで指定される。
  3. 最後のステップはゲームステートの再作成である。このステップが発生するのは新ホストのみで Fusion NetworkRunnerで構成され、StartGamrArgs.HostMigrationResume引数としてパスされるコールバックを起動する。このコールバックはNetworkRunnerが完全に初期化される前に起動するため、デベロッパーはシミュレーション前に古いゲームステートを読み取り、古いNetworkObjectを再作成して必要に応じてそれらをセットアップすることができる。

以下のコードスニペットは上記の説明を表しています。

public class FusionInit : MonoBehaviour, INetworkRunnerCallbacks {

  // other callbacks...

  // Step 1.
  // It happens on the Photon Cloud and there is no direct relation with the code on the peers.

  // Step 2.
  // OnHostMigration callback
  public async void OnHostMigration(NetworkRunner runner, HostMigrationToken hostMigrationToken) {

    // Step 2.1
    // Shutdown the current Runner, this will not be used anymore. Perform any prior setup and tear down of the old Runner

    // The new "ShutdownReason.HostMigration" can be used here to inform why it's being shut down in the "OnShutdown" callback
    await runner.Shutdown(shutdownReason: ShutdownReason.HostMigration);

    // Step 2.2
    // Create a new Runner.
    var newRunner = Instantiate(_runnerPrefab);

    // setup the new runner...

    // Start the new Runner using the "HostMigrationToken" and pass a callback ref in "HostMigrationResume".
    StartGameResult result = await newRunner.StartGame(new StartGameArgs() {
      // SessionName = SessionName,              // ignored, peer never disconnects from the Photon Cloud
      // GameMode = gameMode,                    // ignored, Game Mode comes with the HostMigrationToken
      HostMigrationToken = hostMigrationToken,   // contains all necessary info to restart the Runner
      HostMigrationResume = HostMigrationResume, // this will be invoked to resume the simulation
      // other args
    });

    // Check StartGameResult as usual
    if (result.Ok == false) {
      Debug.LogWarning(result.ShutdownReason);
    } else {
      Debug.Log("Done");
    }
  }

  // Step 3.
  // Resume Simulation on the new Runner
  void HostMigrationResume(NetworkRunner runner) {

    // Get a temporary reference for each NO from the old Host
    foreach (var resumeNO in runner.GetResumeSnapshotNetworkObjects())

      if (
          // Extract any NetworkBehavior used to represent the position/rotation of the NetworkObject
          // this can be either a NetworkTransform or a NetworkRigidBody, for example
          resumeNO.TryGetBehaviour<NetworkPositionRotation>(out var posRot)) {

          runner.Spawn(resumeNO, position: posRot.ReadPosition(), rotation: posRot.ReadRotation(), onBeforeSpawned: (runner, newNO) =>
          {
            // One key aspects of the Host Migration is to have a simple way of restoring the old NetworkObjects state
            // If all state of the old NetworkObject is all what is necessary, just call the NetworkObject.CopyStateFrom
            newNO.CopyStateFrom(resumeNO);

            // and/or

            // If only partial State is necessary, it is possible to copy it only from specific NetworkBehaviours
            if (resumeNO.TryGetBehaviour<NetworkBehaviour>(out var myCustomNetworkBehaviour))
            {
               newNO.GetComponent<NetworkBehaviour>().CopyStateFrom(myCustomNetworkBehaviour);
            }
          });
      }
    }
  }

  public void OnShutdown(NetworkRunner runner, ShutdownReason shutdownReason) {

    // Can check if the Runner is being shutdown because of the Host Migration
    if (shutdownReason == ShutdownReason.HostMigration) {
      // ...
    } else {
      // Or a normal Shutdown
    }
  }
}

トップに戻る

API 概要

  • INetworkRunnerCallbacks.OnHostMigration: ホストマイグレーションを行う必要がある場合に起動。
  • HostMigrationToken: ホストマイグレーション実行時に旧NetworkRunnerからの必要な全情報を含む。StartGameを呼び出す場合は新NetworkRunnerへパスする必要がある。
  • HostMigrationToken.GameMode: ローカルピアが起動することになる新GameMode(ローカルピアはHost または Clientのどちらにもなり得る)。プレイヤーに追加情報を表示するのに便利。
  • StartGameArgs.HostMigrationToken: INetworkRunnerCallbacks.OnHostMigrationコールバックで引数として受信されたHostMigrationTokenを承認。
  • StartGameArgs.HostMigrationResume: ゲームシミュレーションが再始動する前に新ホストでゲームステートの再作成を行う場合にコールバックを承認して起動。
  • NetworkRunner.GetResumeSnapshotNetworkObjects: 反復可能なNetworkObjectsのリストを返し、旧ホストの最新の既知のステートを公開する。新規のFusion Simulationで再度作成する必要のあるものの確認に使用することもできる。
  • NetworkObject.CopyStateFrom: 旧NetworkObjectから新しく作成されたものへ全てのステートをコピーするのに使用
  • NetworkBehaviour.CopyStateFrom: 特定のNetworkBehaviourから新NetworkObjectへ全てのステートをコピーするのに使用
  • ShutdownReason.HostMigration: このShutdownReasonは、NetworkRunnerがシャットダウンした理由をシグナルしホストマイグレーションへ適切に反映させるのに使用。

ドキュメントのトップへ戻る