ホストマイグレーション API
概要
Photon Fusionは様々なアーキテクチャに対応しています。そのうちの1つはClient Hostedトポロジで、FusionではHostMode
と呼んでいます。HostMode
とはゲームセッション内のクライアントがゲームの ホスト としての役目を追うものです。クライアントホストはローカルコンピュータから新しくゲームセッションを作成して提供を行い、そのマシンをゲームセッションのサーバーとして他のプレイヤーのプレイ接続を許可します。
主なメリットは主なデメリットでもあります。インフラストラクチャのコントロールがしづらいということです。以下の様な場合にはゲームセッションの品質が落ちたり、停止したりします。
- 家庭用ネットワーク上のトラフィックの品質にはばらつきがある場合。これはゲームホストのインターネット接続/サブスクリプションによるもの。; and,
- 電源が落ちたりシャットダウンされることでホストマシンが落ちる場合(システムアップデートまたはプレイヤーの手による)
この双方のポイントが、特にゲームセッションが停止された直後において、プレイヤー体験を悪化させる可能性があります。HostMode
のFusionゲームが稼働するのがゲームサーバーが存在する場合のみであるためです。
この問題を解決するため、Fusionはデベロッパーが統合できるHost Migration API/システム
を搭載しています。Fusionのホストマイグレーション機能を活用するとゲームセッション内の他のクライアントピアにゲームのホストを引き継ぐことができ、ゲームせしょんを引き続き行うことができます。これはゲーム体験全体にプラスに働き、専用サーバーでのServerMode
のヘッドレスインスタンスを稼働させる野に必要なインフラストラクチャの実質的な代替案となります。
備考: 実装例はFusion Host Migration Sampleでご覧いただけます。
ホストマイグレーション
ホストマイグレーションの事項には、いくつかの前提条件が必要となります。
- Fusionの開始時、ピアの1人がホスト(同一マシンでサーバーおよびプレイヤーとなる)としてシミュレーションを開始する必要があります。これは、
GameMode.Host
またはGameMode.AutoHostOrClient
パラメータを使用して、Fusion Simulation (NetworkRunner.StartGame()
)を起動することで実行可能。 - ホストマイグレーションの有効化。ホストマイグレーションは オプション 機能のため、実装に手動作業が必要となります。デフォルトでは有効になっていません。
- ゲームの移行準備を行います。ホストを他のマシンに移行するのは簡単ではありませんが、Fusionではこれをできるだけシンプルにしています。このシステムは、旧ホストのゲーム状態全体にアクセスすることができ、移行プロセスに入るもの、出るものを強制するものではありません。
ホストマイグレーションの有効化
ホストマイグレーションを有効にするには、Fusion > Network Project Config
メニューからNetworkProjectConfig
を開き、アセットのConfig
セクションで以下の設定を確認します。
Enable Host Migration
: ボックスにチェックを入れるとホストマイグレーションシステムが有効になります。Host Migration Snapshot Interval
: PhotonCloudへスナップショットを送信するための秒単位でのインターバル。適切な値はゲームのペースによって異なります。多くの場合、30秒が推奨されます。クラウドに保存されるのは最新のスナップショットのみのため、ホスト移行が必要になり最後のスナップショット間のゲームステートに変更が生じると実際のホストマイグレーションは失われます。
ホストマイグレーションを実行する
ホストマイグレーションの中心となるエントリポイントはINetworkRunnerCallbacks.OnHostMigration
コールバックです。ゲームがホストマイグレーションの実行を必要とするとOnHostMigration()
が起動されます。
Fusionは 旧 ホストのゲームステートを反復可能なNetworkObjects
のリストとして公開します。ここには、 新 ホストがゲームステートの再構築する際に、前回のものとできるだけ同様のものにするのに必要なデータが含まれます。
ホストマイグレーションのプロセスは以下の通りです。
- Fusion Server Plugin(Photon Cloudでのホスティング)がホストピアのセッション退出を検知すると、その他の全ピアでホストマイグレーションプロセスが起動される。この時点では、
- 新しいホストが選出され、;
- 旧 ホストから受信した、最後に保存されたゲームステートが 新 ホストに送信される。 重要: このスナップショットが送信されるのは新ホストのみで、その他のピアには送信されない。
INetworkRunnerCallbacks.OnHostMigration
コールバックが起動され、マイグレーションプロセスが開始される。- 現在のFusion NetworkRunnerはまだ稼働状態のため、手動でシャットダウンする必要がある。デベロッパーは、マイグレーション自体を実行する前に必要なリセットおよび・またはセットアップを行うことができる。
- 新しいホストに接続してゲームを再開するために新しいFusion
NetworkRunner
が作成される必要がある。旧Runnerの再使用はサポートされていない。旧ゲームについての必要な情報は全てHostMigrationToken
によって転送される。これはOnHostMigration
コールバックから取得可能。このステップは新ホストと接続中の新クライアントの双方で行われる。特定のピアで使用されるSessionName
とGameMode
はどちらもHostMigrationToken
で指定される。
- 最後のステップはゲームステートの再作成である。このステップが発生するのは新ホストのみで Fusion
NetworkRunner
で構成され、StartGamrArgs.HostMigrationResume
引数としてパスされるコールバックを起動する。このコールバックはNetworkRunner
が完全に初期化される前に起動するため、デベロッパーはシミュレーション前に古いゲームステートを読み取り、古いNetworkObject
を再作成して必要に応じてそれらをセットアップすることができる。
以下のコードスニペットは上記の説明を表しています。
C#
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
がシャットダウンした理由をシグナルしホストマイグレーションへ適切に反映させるのに使用。