オンラインセッション
概要
Quantum のオンラインサービスは、一般的な Photon オンラインインフラストラクチャ(Photon Realtime)の上に構築されています。オンラインセッションへの接続は通常、3つの接続フェーズを経て行われます。
- カスタム認証:Photon はプレイヤーアカウントを提供せず、プロプライエタリまたはサードパーティの認証プロバイダを使用してログインを保護することを推奨し、Photon カスタム認証を設定します。
- ゲームサーバー接続:オンラインシミュレーションを開始する前に、クライアントは Photon Cloud に接続し、Photon Realtime API を使用して Photon Room に入室する必要があります。
- Quantum シミュレーション開始シーケンス:このフェーズでは、Quantum シミュレーションが開始および同期され、クライアントの設定とプレイヤーデータが送信されます。
ゲームサーバー接続
これは、Photon Cloud に接続し、ゲームサーバーでマッチメイキングするための最も簡単な方法です。
C#
var connectionArguments = new MatchmakingArguments {
// Photon アプリケーションの設定
PhotonSettings = PhotonServerSettings.Global.AppSettings,
// Photon ルームを作成する際に "EnterRoomArgs.RoomOptions.PlayerTtl" として設定される
PlayerTtlInSeconds = 10,
// Photon ルームを作成する際に "EnterRoomArgs.RoomOptions.EmptyRoomTtl" として設定される
EmptyRoomTtlInSeconds = 10,
// Photon ルームを作成する際に "EnterRoomArgs.RoomOptions.RoomName" として設定される
RoomName = "room-name",
// ルームの最大クライアント数。ここでは Quantum シミュレーションのためのコード生成された最大可能プレイヤーを使用
MaxPlayers = Input.MAX_COUNT,
// 接続リクエストでルームを作成できるか、または参加のみを試みるかを設定
CanOnlyJoin = false,
// "EnterRoomArgs.RoomOptions.CustomRoomProperties" として設定されるカスタムルームプロパティ
CustomProperties = customRoomProperties,
// TaskFactory とグローバルキャンセルサポートを含む非同期設定。null の場合は "AsyncConfig.Global" が使用される
AsyncConfig = customAsyncConfig,
// Photon サーバー接続の認証値を提供。これをカスタム認証と共に使用。このフィールドは "UserId" が設定されたときに作成される
AuthValues = customAuthValues,
// Photon Cloud にリクエストするプラグイン
PluginName = "QuantumPlugin",
// 再接続情報を保存およびロードするためのオプションのオブジェクト
ReconnectInformation = new MatchmakingReconnectInformation(),
// マッチメイキングに使用するオプションのリアルタイムロビー
Lobby = new TypedLobby(),
// AuthValues を設定し、カスタム認証を置き換える必要がある
UserId = Guid.NewGuid().ToString(),
};
// この行は Photon Cloud に接続し、引数に基づいてマッチメイキングを行い、最終的にルームに入ります。
RealtimeClient Client = await MatchmakingExtensions.ConnectToRoomAsync(connectionArguments);
良いプラクティスは、ConnectToRoomAsync 手続きを Try Catch
ステートメントでカプセル化することです。考えられる例外は以下の通りです:
ReconnectInformation missing
引数が null の時;AppVersion mismatch
ReconnectInformation.AppVersion が PhotonSettings.AppVersion と異なる;UserId not set
ReconnectInformation.UserId が null または空;UserId mismatch
ReconnectInformation と AuthValues が異なる UserId を持つ;TaskCanceledException
AsyncConfig.CancellationToken でキャンセルトークンが要求された。
AppSettings
Photon Cloud に接続するために、AppSettings
と呼ばれる設定が必要です。Quantum 統合内では、通常は Singleton パターンを介してアクセスされます:PhotonServerSettings.Instance.AppSettings
。もちろん、正しいデータを注入する別の方法と交換できます。
設定オブジェクトはコピーされることに注意してください。そうしないと、アセットへの変更が保存されるリスクがあります。
C#
var appSettings = PhotonServerSettings.CloneAppSettings(PhotonServerSettings.Instance.AppSettings);
appId を設定するには、次の指示に従ってください:Quantum Asteroids Tutorial - Project Setup
Quantum シミュレーション開始シーケンス
以下のスニペットは、オンライン Quantum セッションを開始する基本的な操作を示しています。
C#
var sessionRunnerArguments = new SessionRunner.Arguments {
// ランナーファクトリは Quantum.Runner と Unity の接着剤です
RunnerFactory = QuantumRunnerUnityFactory.DefaultFactory,
// `QuantumGameStartParameters` のデフォルトバージョンを作成します
GameParameters = QuantumRunnerUnityFactory.CreateGameParameters,
// たとえば、実行中のセッションに再接続するためにプレイヤースロットを確保するために使用される秘密のユーザーID
ClientId = Client.UserId,
// プレイヤーデータ
RuntimeConfig = runtimeConfig,
// Unity アセットからロードされたセッション設定。タグ付けは `QuantumDefaultGlobal`
SessionConfig = QuantumDeterministicSessionConfigAsset.DefaultConfig,
// ゲームモードはオンラインセッションのためにマルチプレイヤーでなければなりません
GameMode = DeterministicGameMode.Multiplayer,
// セッションが実行されるプレイヤーの数。この場合、Quantum シミュレーションのためのコード生成された最大可能プレイヤーを使用
PlayerCount = Input.MAX_COUNT,
// 接続ロジックと Quantum プロトコルが失敗するタイムアウト
StartGameTimeoutInSeconds = 10,
// シミュレーションが開始された後、ネットワーク処理を引き継ぐコミュニケーター
Communicator = new QuantumNetworkCommunicator(Client),
};
// このメソッドは、クライアントがオンラインセッションに正常に参加したときに完了します
QuantumRunner runner = (QuantumRunner)await SessionRunner.StartAsync(sessionRunnerArguments);
プレイヤーの追加と削除
Quantum にはプレイヤーの概念があります。各クライアントはゼロまたは複数のプレイヤーを持つことができます。Quantum オンラインセッションを初めて開始すると、クライアントはプレイヤーが明示的に追加されるまで観客の状態にあります。
ゲームに接続されている各プレイヤーにはユニークな ID が割り当てられます。この ID は PlayerRef
と呼ばれ、しばしば Player
と呼ばれます。
Quantum 2.1 とは異なり、プレイヤーはいつでも追加および削除できます。
プレイヤーは「PlayerSlots」と呼ばれるスロットを占有します。これは常に、1 つのクライアントが自分のプレイヤーを管理する方法を示します。ローカルプレイヤースロットが 1 つのみ使用される場合、それはスロット 0
になります。そのクライアントによって制御される 2 番目のプレイヤーは PlayerSlot
1 を持っている可能性があります。典型的な使用例として、CallbackPollInput
コールバックがあります。これは、どのローカルプレイヤーの入力がポーリングされるかを制御するために PlayerSlot
プロパティを使用します:QuantumGame.AddPlayer(Int32 playerSlot, RuntimePlayer data)
。
AddPlayer()
は、カスタマーのバックエンドに HTTP リクエストを発生させる可能性があるため、操作にはサーバー側にレート制限があります。スパムすることはできません。
RuntimePlayer
Quantum には、プレイヤーオブジェクトやプレイヤーアバターの組み込みの概念がありません。
プレイヤーに関連するゲーム情報(キャラクターの装備、キャラクターレベルなど)は、各クライアントによって RuntimePlayer
オブジェクトを使用してシミュレーションに渡されます。
C#
// プレイヤーをプレイヤースロット 0 に追加します
QuantumRunner.Default.Game.AddPlayer(runtimePlayer);
正確なプレイヤースロットを指定するには、QuantumGame.AddPlayer(int playerSlot, RuntimePlayer data)
を使用します。以下の例のように。
C#
// プレイヤーをプレイヤースロット 1 に追加します
QuantumRunner.Default.Game.AddPlayer(1, runtimePlayer);
PlayerConnectedSystem
プレイヤーが Quantum セッションに接続しているかを追跡するために Input & Connection Flags が使用されます。 PlayerConnectedSystem
はこのプロセスを自動化し、プレイヤーがセッションに接続または切断された場合にシミュレーションに通知します。
接続と切断のコールバックを受け取るために、ISignalOnPlayerConnected
および ISignalOnPlayerDisconnected
をシステム内で実装する必要があります。
利用可能なローカルプレイヤーコールバック
ローカルプレイヤーを処理するための便利なコールバックもあります:CallbackLocalPlayerAddConfirmed
, CallbackLocalPlayerRemoveConfirmed
, CallbackLocalPlayerAddFailed
, CallbackLocalPlayerRemoveFailed
。
C#
QuantumCallback.Subscribe(this, (CallbackLocalPlayerAddConfirmed c) => OnLocalPlayerAddConfirmed(c));
QuantumCallback.Subscribe(this, (CallbackLocalPlayerRemoveConfirmed c) => OnLocalPlayerRemoveConfirmed(c));
QuantumCallback.Subscribe(this, (CallbackLocalPlayerAddFailed c) => OnLocalPlayerAddFailed(c));
QuantumCallback.Subscribe(this, (CallbackLocalPlayerRemoveFailed c) => OnLocalPlayerRemoveFailed(c));
セッションの停止と切断
Quantum シミュレーションを停止するには、QuantumRunner.ShutdownAll(bool immediate)
を実行します。これは Quantum コールバック内 から呼び出されていない場合にのみ immediate:true
を設定します。もし Shutdown コマンドが Quantum コールバック内で呼ばれる場合は、immediate:false
を設定することが重要です。この場合、シャットダウンは次の Unity 更新まで延期されます。
ShutdownAll
は QuantumRunner オブジェクトを破棄し、ローカル Quantum シミュレーションが停止されます。これにより、Disconnect()
または LeaveRoom()
のいずれかが実行され、StartParameters.QuitBehaviour
に設定されている内容に依存します。
クライアントがゲームを正常に終了する場合(たとえば、リモートクライアントのプレイヤーアバターをクリーンアップするため)、シミュレーション内に追加のロジックを実装する必要があります。これは、クライアントが発行したコマンドまたは接続された状態を監視すること(PlayerConnectedSystem
を参照)によって実行できます。
プレイヤーがアプリを閉じたり、ゲームを Alt+F4 で終了したりすることを考慮に入れると、優雅な切断を送信する機会が常にあるとは限りません。
C#
async void Disconnect() {
// すべてのランナーにシャットダウンを通知し、各ランナーが切断するまで待機します
await QuantumRunner.ShutdownAllAsync();
// または、単にシャットダウンを通知します
QuantumRunner.ShutdownAll();
}
プラグイン切断エラー
Quantum プラグインがクライアントの開始プロトコルや入力メッセージにエラーが発生した場合、接続を優雅に終了させる操作を送信します。この場合、クライアントで CallbackPluginDisconnect
コールバックが発火し、詳細を含む Reason
文字列が提供されます。このようなエラーは回復不可能であり、クライアントは再接続し、シミュレーションを再起動する必要があります。
Error #3 |
Must request start before any protocol message or input messages other than 'StartRequest' is accepted |
クライアントが開始リクエストを送信する前にプロトコルまたは入力メッセージを送信しようとしました。 |
Error #5 |
Duplicate client id |
クライアントがすでに使用されているClientId でゲームを開始しようとしました。 |
Error #7 |
Client protocol version '2.2.0.0' is not matching server protocol version '3.0.0.0' |
クライアントが互換性のないプロトコルバージョンでゲームを開始しようとしました。 |
Error #8 |
Invalid client id 'NULL' |
クライアントがClientId を指定せずにゲームを開始しようとしました。 |
Error #9 |
Server refused client |
カスタムプラグインがクライアントのセッション参加を拒否しました。 |
Error #12 |
Operation not allowed when running in spectating mode |
クライアントが観客モード(プレイヤーが追加されていない状態)でコマンドを送信しようとしました。 |
Error #13 |
Snapshot request failed to start |
クライアントが遅れてゲームに参加しましたが、参加するためのスナップショットを提供するのに適切な接続されたプレイヤーがいませんでした。 |
Error #16 |
Player corrupted |
クライアントがプロトコルまたは入力メッセージのデシリアライズ中にプラグインで例外を引き起こしました。このエラーは、クライアント接続でパケット CRC チェックを有効にすることで対処できます:RealtimeClient.RealtimePeer.CrcEnabled = true 。 |
Error #17 |
PlayerCount is not valid |
クライアントが無効なプレイヤー数でオンラインゲームを開始しました。 |
Error #19 |
Player not found |
クライアントが所有していないPlayerSlot に対してコマンドを送信しました。 |
Error #20 |
RPC data corrupted |
プレイヤーを追加する際のRuntimePlayer オブジェクトまたはコマンドデータが大きすぎました(最大 24 KB)。 |
Error #21 |
Quantum SDK 2 not supported on Quantum 3 AppIds, check Photon dashboard to set correct version |
Quantum SDK 2.1 を使用しているクライアントが Quantum 3 AppId で接続しようとしました。 |
Error #33 |
Player data was rejected 'Webhook Error Message' |
プレイヤー追加の webhook が失敗しました。 |
Error #34 |
Game configs not loaded 'Webhook Error Message' |
ゲーム設定の webhook が失敗し、すべてのクライアントが切断されました。 |
Error #40 |
Caught exception receiving protocol messages |
クライアントがプロトコルメッセージを処理する際に例外が発生しました。これは必ずしもサーバーエラーではなく、クライアントの状態は回復不能で切断されます。 |
Error #41 |
Input cache full |
クライアントのローカルデルタ圧縮入力バッファが満杯で、長時間のブレークポイントで発生する可能性があります。この状態はクライアントにとって回復不可能です。 |
Error #42 |
Communicator not connected |
シミュレーションが実行中に接続が失われました。これを防ぐためには、たとえば Photon Realtime コールバックを使用して切断を早期に検出する必要があります。 |
Error #51 |
Snapshot download timeout |
サーバーがデフォルトのタイムアウトである 20 秒内にすべての必要なスナップショットフラグメントを送信できませんでした。 |
Error #52 |
Snapshot upload timeout |
要求されたバディスナップショットがデフォルトのタイムアウトである 10 秒以内にアップロードされませんでした。 |
Error #53 |
Snapshot upload error |
アップロードされたバディスナップショットにエラーが含まれていました。 |
Error #54 |
Snapshot upload disconnected |
遅延参加がバディスナップショットをアップロード中にクライアントが切断されたため中断されました。 |