This document is about: QUANTUM 3
SWITCH TO

オンラインセッション

概要

Quamtumのオンラインサービスは、Photon共通のオンラインインフラストラクチャ(Photon Realtime)上に構築されています。オンラインセッションへの接続は、通常は3つの接続フェーズを経て行われます。

  1. カスタム認証:Photonはプレイヤーアカウントを提供しないため、独自またはサードパーティー製の認証プロバイダーを使用して安全にログインし、Photonのカスタム認証を行うことを推奨します。
  2. ゲームサーバー接続:オンラインシミュレーションを開始する前に、クライアントはPhoton Cloudに接続し、Photon Realtime APIを使用してPhotonのルームに参加する必要があります。
  3. Quantumシミュレーション開始シーケンス:このフェーズでQuantumシミュレーションの開始・同期を行い、クライアント設定とプレイヤーデータを送信します。

ゲームサーバー接続

Photon Cloudへの接続を確立し、ゲームサーバーへマッチメイキングするための最も簡単な方法は次の通りです。

C#

var connectionArguments = new MatchmakingArguments {
    // アプリケーションの情報を含むPhotonAppSettingsです。
    PhotonSettings = PhotonServerSettings.Global.AppSettings,
    // Photon Cloudに設定するようにリクエストするプラグインです。
    PluginName = "QuantumPlugin"
    // 明示的にルーム名を指定すると、CanOnlyJoinの設定に基づいてルームの作成/参加が試みられます。RoomNameをnullにすると、ルーム作成時にユニークな名前が付きます。
    RoomName = "My Room Name",
    // ルームに接続できる最大クライアント数で、大抵のケースでは、Quantumシミュレーションの最大プレイヤー数と同じになります。
    MaxPlayers = Input.MAX_COUNT,
    // 参加のみを試みるか?ルーム作成もリクエストするか?を設定します。
    CanOnlyJoin = false,
    // カスタム認証に置き換えたら、ここで明示的にAuthValuesを設定します。
    UserId = Guid.NewGuid().ToString(),
};

// Photon Cloudに接続し、引数に基づいてマッチメイキングを行い、最終的にルームへ参加します。
RealtimeClient Client = await MatchmakingExtensions.ConnectToRoomAsync(connectionArguments);

実践的には、ConnectToRoomAsync()/ReconnectToRoomAsync()Try Catchで囲んでください。または、他のTaskに例外を投げてください。

C#

var client = default(RealtimeClient);
try {
    client = await MatchmakingExtensions.ConnectToRoomAsync(connectionArguments);
} catch (Exception e) {
    // 何か予期せぬことが発生した場合、
    // 詳細なエラー処理を行う必要はまず無いので、一般的なフィードバックとしてログを表示し、再試行を促します。
    Debug.LogException(e);
}

ConnectToRoomAsync()中に投げられる例外の例は次の通りです。

  • Failed to connect and join with error 'X':Photon Cloud接続がエラーで失敗した場合
  • MaxPlayer must be greater or equal than 0
  • MaxPlayer must be less than 256
  • PhotonSettings must be set
  • TaskCanceledExceptionAsyncConfig.CancellationTokenでキャンセルがリクエストされた場合

ReconnectToRoomAsync()中に投げられる例外の例は次の通りです。

  • AppVersion mismatchReconnectInformation.AppVersionPhotonSettings.AppVersionと異なる場合
  • UserId not setReconnectInformation.UserIdnullか空の場合
  • UserId mismatchReconnectInformationAuthValuesUserIdが異なる場合
  • ReconnectInformation timed outReconnectInformationが古い場合
  • ReconnectInformation missingReconnectInformationnullの場合

AppSettings

Photon Cloudに接続するためには、AppSettingsと呼ばれる設定が必要です。Unityプロジェクトでは、PhotonServerSettings.Instance.AppSettingsからグローバルアセットにアクセスできます。

設定オブジェクトは常にコピーするようにして、UnityエディターのPhotonServerSettingsアセットへ変更が保存されないようにしてください。

C#

var appSettings = new AppSettings(PhotonServerSettings.Global.AppSettings);

Photon AppIdのセットアップについては、Quantum Asteroids チュートリアル - プロジェクトの準備をご覧ください。

MatchmakingArgumentsのオプション

MatchmakingArgumentsでは、以下のようなオプション引数が利用できます。

詳細はPhoton Realtimeのマッチメイキングガイドをご覧ください。

AsyncConfig TaskFactoryとグローバルのキャンセル対応を含む非同期設定です。nullの場合、AsyncConfig.Globalが使用されます。
NetworkClient Realtimeのクライアントオブジェクトを指定します。nullの場合、マッチメイキング処理中に新しいクライアントオブジェクトが作成されます。
ReconnectInformation NetworkClientインスタンスを失った後(例:アプリケーションの再起動後)の再接続のために使用されます。

QuantumReconnectInformationにはPlayerPrefsなどの情報が格納されます。使用例については、Quantumデモメニューをご覧ください。
EmptyRoomTtlInSeconds 最後のクライアントが退出した後、空のPhotonルームが残る時間(秒)です。

内部的にはRoomOptions.EmptyRoomTtlが設定されます。
PlayerTtlInSeconds 切断されたクライアントがサーバーで非アクティブになった後、ReconnectAndRejoin()で再接続できる時間(秒)です。

内部的にはRoomOptions.PlayerTtlが設定されます。
AuthValues Photonサーバー接続の認証値を指定します。これはカスタム認証と合わせて使用されます。

UserIdが設定されると、このフィールドが作成されます。
CustomProperties ルームの(初期の/期待する)ルームプロパティを設定します。マッチメイキングで使用されるプロパティ名はCustomLobbyPropertiesを使用してください。

内部的にはRoomOptions.CustomRoomPropertiesが設定されます。
CustomLobbyProperties ロビー内のクライアントが利用可能なカスタムルームプロパティです。これによって、CustomPropertiesキーバリューペアが同一のクライアントのみをマッチングさせます。

内部的にはRoomOptions.CustomRoomPropertiesForLobbyが設定されます。
Lobby マッチングに使用するロビーです。このタイプはフィルターの適用に影響します。

内部的にはEnterRoomArgs.LobbyJoinRandomRoomArgs.Lobbyが設定されます。
SqlLobbyFilter マッチングをフィルタリングするSQLクエリです。デフォルトタイプのロビーでは、かわりにExpectedCustomRoomPropertiesを使用してください。

内部的にはJoinRandomRoomArgs.SqlLobbyFilterが設定されます。
Ticket カスタムサーバー署名付きのマッチメイキング用チケットです。

内部的にはEnterRoomArgs.TicketJoinRandomRoomArgs.Ticketが設定されます。
RandomMatchingType MatchmakingModeはルームの埋め方に影響します。

FillRoom - (デフォルト値)プレイヤーを出来るだけ素早く集めるために(古いルームから最初に)ルームを埋めていきます。
SerialMatching - 存在するルーム間でプレイヤーを順次に分散します。フィルターが考慮されますが、フィルターが無い場合は、ルームにプレイヤーが均等に分散します。
RandomMatching - 完全にランダムにルームへ参加します。ルームプロパティが一致している必要がある以外は、すべての空きルームが選択される可能性があります。

内部的にはJoinRandomRoomArgs.MatchingTypeが設定されます。
ExpectedUsers このクライアントと一緒にルームに参加する予定のユーザーリストです。MaxPlayers値でルームのスロットを予約します。

内部的にはEnterRoomArgs.ExpectedUserJoinRandomRoomArgs.ExpectedUsersが設定されます。
CustomRoomOptions 他の引数から構成されるEnterRoomArgs.RoomOptionsを完全に置き換えます。
IsRoomVisible nullでない場合、RoomOptions.IsVisibleの初期値になります。
IsRoomOpen nullでない場合、RoomOptions.IsOpenの初期値になります。
EnableCrc 有効にすると、クライアントとサーバーで送信されるすべてのパッケージに、CRCチェックサムが追加されます。このチェックサムによって、転送中に破損したパッケージを検知して無視できます。破損したパッケージは損失したパッケージと同様に、再送が必要になる分だけ遅延が発生し、タイムアウトに繋がる可能性があります。チェックサムの追加による処理のオーバーヘッドは少ないですが、送受信データの完全性を高めます。CRCチェックに失敗して破棄されたパッケージはPhotonPeer.PacketLossByCrcにカウントされます。

Quantumシミュレーション開始シーケンス

以下のスニペットは、Quantumのオンラインセッションを開始する基本的な操作を示します。

C#

var sessionRunnerArguments = new SessionRunner.Arguments {
    // RunnerFactoryによって、Quantum.RunnerとUnityを結合します
    RunnerFactory = QuantumRunnerUnityFactory.DefaultFactory,
    // デフォルトのQuantumGameStartParametersを作成します
    GameParameters = QuantumRunnerUnityFactory.CreateGameParameters,
    // 実行中のセッションへ再接続するためのプレイヤースロットを確保する際に使用される秘密のユーザーIDです
    ClientId = Client.UserId,
    // プレイヤーのデータです
    RuntimeConfig = runtimeConfig,
    // QuantumDefaultGlobalでタグ付けされたUnityアセットからロードされるセッション設定です
    SessionConfig = QuantumDeterministicSessionConfigAsset.DefaultConfig,
    // オンラインセッションのGameModeはMultiplayerにする必要があります
    GameMode = DeterministicGameMode.Multiplayer,
    // セッションの最大プレイヤー数です。ここでは、コード生成されたQuantumシミュレーションの最大プレイヤー数を使用します。
    PlayerCount = Input.MAX_COUNT,
    // 接続ロジックとQuantumプロトコルが失敗するタイムアウト時間です
    StartGameTimeoutInSeconds = 10,
    // Communicatorは、シミュレーション開始後にネットワーク処理を引き継ぎます
    Communicator = new QuantumNetworkCommunicator(Client),
};

// クライアントがオンラインセッションへ正常に参加するとメソッドが完了します
QuantumRunner runner = (QuantumRunner)await SessionRunner.StartAsync(sessionRunnerArguments);

プレイヤーの追加/削除

Quantumにはプレイヤーの概念があります。各クライアントは0~複数のプレイヤーを持つことができます。Quantumオンラインセッションを開始してからプレイヤーを明示的に追加するまで、クライアントは観客の状態になります。

ゲームに接続している各プレイヤーには、ユニークIDが割り当てられます。このIDはPlayerRefと呼ばれ、Playerとして参照されます。

Quantum 2.1とは異なり、プレイヤーはいつでも追加/削除できます。

プレイヤーが占有するPlayerSlotsは、クライアントが自身のプレイヤーを管理するために参照されます。ローカルプレイヤースロットが1つのみ使用される場合、そのスロットは0になります。クライアントが2番目のプレイヤーを制御する場合は、PlayerSlot1になります。典型的な使用例は、入力コールバックCallbackPollInputで、どのローカルプレイヤー入力をポーリングするかを制御する際(QuantumGame.AddPlayer(Int32 playerSlot, RuntimePlayer data))にPlayerSlotプロパティを使用します。

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セッションへのプレイヤー接続を追跡するために、入力と接続フラグが使用されます。PlayerConnectedSystemはこのプロセスを自動化し、プレイヤーのセッションへの接続/切断をシミュレーションに通知します。

接続/切断のコールバックを受け取るには、システムにISignalOnPlayerConnected/ISignalOnPlayerDisconnectedを実装する必要があります。

ローカルプレイヤーの便利なコールバック

ローカルプレイヤー処理に便利なコールバックとして、CallbackLocalPlayerAddConfirmedCallbackLocalPlayerRemoveConfirmedCallbackLocalPlayerAddFailedCallbackLocalPlayerRemoveFailedがあります。

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更新までシャットダウンが延期されます。

ShutdownAllQuantumRunnerオブジェクトを破棄し、Quantumローカルシミュレーションの停止がトリガーされます。StartParameters.QuitBehaviourの設定値によって、Disconnect()/LeaveRoom()のいずれかが実行されます。

クライアントがゲームを正常に終了する(例:プレイヤーアバターを後片付けする)場合は、シミュレーションで追加のロジックを実装する必要があります。これには、クライアントが発行したコマンドか、プレイヤー接続状態(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オブジェクトまたはコマンドデータが大きすぎます(最大24KB)。
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 #22 Tick violation, type=RPC, requested=694, current=93 サーバーが過剰に入力やコマンドを送信しているクライアントを検知して切断しました。これは、クライアントが非常に遠い未来の入力を送信していたり、長時間に渡って大量のコマンドを送信していたりする場合に起こります。
Error #30 Create game failed Exception Message ゲーム作成中にクライアントで例外が発生しました。
Error #31 Create game failed Webhook Error Message CreateGameのWebhookが失敗しました。
Error #32 Join game failed Webhook Error Message JoinGameのWebhookが失敗しました。
Error #33 Player data was rejected Webhook Error Message AddPlayerの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 バディスナップショットをアップロードするクライアントが切断されたため、途中参加が中断されました。
Back to top