Webhooks
概要
Webhookは、信頼できるゲーム設定やルーム構成の情報源として主に利用され、オンラインアプリケーションの安全性向上に大きく寄与します。
デフォルトのクラウドプラグインは、AppIDダッシュボードで定義されたさまざまなWebhookをサポートしています。設定と有効化を行うと、Photon CloudはカスタムバックエンドへHTTP POSTリクエストを送信し、そのレスポンスデータ(JSON)を活用して、ルームやゲームセッションの各種構成を適用します。
セットアップ
WebhookはPhotonダッシュボード上でAppIdごとにセットアップを行います。
- Photon Dashboard へナビゲートし、ログインする。
- AppIdを探し、
Manage
をクリックする。 - プラグインまでスクロールで下がり、
Edit
をクリックする。 Add New Pair
をクリックして、keys
とvalues
(各設定値に使えるのは最大1024文字)を追加する。Save
を押下して最大1分間待ち変更が反映されたことを確認する。

ダッシュボード設定
Key | Type | Example | Description |
---|---|---|---|
WebHookBaseUrl | string |
https://localhost:3581 |
カスタムバックエンドの基本URLです。WebhookのパスはこのURLに追加され、次の形式になります: {WebHookBaseUrl}/game/create 必ず設定してください。 |
WebHookIntegration | string |
Default |
選択されたWebhookの統合方法です(デフォルトは `Default `)。選択肢は以下の通りです: Default 、PlayFab |
WebHookSecret | string |
********** |
これらは各Webリクエストとともに送信され、リクエストの認証に利用できます。 ヘッダー名は ` X-SecretKey ` に設定されます。 |
WebHookCustomHttpHeaders | Dictionary <string, string> |
{"A": "Foo", "B": "100" } |
`JSON`形式の辞書です。すべてのエントリーはカスタムWebリクエストのヘッダーに追加されます。ダブルクォーテーションを使用してください。 |
WebHookEnableOnCreate | bool |
true |
これを`true`に設定すると、クライアントがゲームセッションを作成するときに`CreateGame`Webhookが発動します。 |
WebHookEnableOnClose | bool |
false |
これを`true`に設定すると、ゲームセッションが閉じられた際に `CloseGame` Webhookが発動します。 |
WebHookEnableOnJoin | bool |
true |
これを`true`に設定すると、クライアントがゲームセッションに参加しようとした際に`JoinGame` Webhookが発動します。 |
WebHookEnableOnLeave | bool |
false |
これを`true`に設定すると、クライアントがゲームセッションを退出した際に `LeaveGame` Webhookが発動します。 |
WebHookUrl{KEY} | string |
https://foo.net/path |
このパターンは任意で、`WebHookBaseUrl`に基づいて個別のWebhookのデフォルトパスを上書きするために使用できます。 ` {KEY} ` の有効な置換文字列は、`OnCreate `、`OnJoin `、`OnLeave `などです。 |
Quantum Dashboard Configurations
Key | Type | Example | Description |
---|---|---|---|
WebHookEnableGameConfigs | bool |
false |
If set to true , the GameConfigs webhook will be fired when a client uploaded the game configs RuntimeConfig and SessionConfig using the StartRequest operation. |
WebHookEnableGameResult | bool |
false |
If set to true , the GameResult webhook will be invoked. |
WebHookEnableAddPlayer | bool |
false |
If set to true , the client operation AddPlayer will invoke the AddPlayer web request. |
WebHookEnablePlayerAdded | bool |
false |
If set to true , the PlayerAdded web request is invoked after a player has been successfully added to the Quantum online game. |
WebHookEnablePlayerRemoved | bool |
false |
If set to true , the PlayerRemoved web request is invoked after a player was removed from the Quantum game. |
WebHookEnableReplay | bool |
false |
Setting this to true will enable the replay streaming based on the ReplayStart and ReplayChunk web requests. |
Webhook API
WebhooksはJSONコンテンツを送信し、レスポンスもJSON形式のコンテンツのみを受け付けます。JSONの文字エンコーディングはUTF-8
のみが必須です。
WebhooksはHTTPレスポンスコードとして200
または400
を期待しています。
200
: リクエスト成功400
: エラーまたは操作が拒否された(例:クライアントによるルームやゲームセッションの作成を許可しない場合)
Photonサーバーは、通信エラー時にWebhookのリトライを3回行います。リトライ間の遅延は、400ms、1600ms、6400msです。また、リクエストが失敗し再試行されないまでのタイムアウト時間は10秒です。
エラーの詳細情報をPhotonプラグインに返すために、WebhookErrorの定義を記入してください。これにより、以下の用途に利用できます:
- ロギング
- クライアントへの情報返還
- カスタムプラグインによる高度なエラー処理
Httpリクエスト再試行
Photonサーバーは、バックエンドからの再試行可能なエラー応答に対して、リクエストをさらに3回再送信します。
その後のリクエストには、それらを識別するための異なるヘッダーが付加されます。
EGRepeatId
- 例えば、0
、1
、2
、3
などの整数値で、リクエストの再送番号。
EGInvokeId
- リクエストID (整数)
よくあるリクエストヘッダ
Tこれらの共通リクエストヘッダーは、すべての ウェブリクエストに追加されます。
Name | Type | Content | Description |
---|---|---|---|
Accept |
string |
application/json |
Webhooksは、レスポンス本文として JSON 形式のみを受け付けます |
Accept-Charset |
string |
utf-8 |
Webhooksは、レスポンスの本文の文字エンコーディングとしてUTF-8のみを受け付けます |
Content-Type |
string |
application/json |
すべてのWebhooksは、 JSON 形式の本文データを送信します |
X-SecretKey |
string |
********** |
このキーはカスタムバックエンドのみが知っているべきものであり、受信するウェブリクエストの認証に使われます。PhotonダッシュボードでWebHookSecret と設定されます。 |
X-Origin |
string |
Photon |
必ず"Photon"と設定 |
CreateGame
このWebhookは、ルームまたはゲームセッションがPhotonサーバー上で作成される前に呼び出されます。Webhookがレスポンスを受け取るまで作成はブロックされるため、これによりクライアントが接続を確立するまでの時間に影響します。
CreateGameWebhook
は、常にルームまたはゲームセッションの作成を開始したユーザーのJoinGameリクエストとして扱われます。このユーザーに対して後続のJoinGameWebhook
は発生しません。このWebhookは、JoinGameWebhook
のデータを共有します。
このWebhookを設定するには、PhotonダッシュボードでWebHookBaseUrl
とWebHookEnableCreateGame
を設定している必要があります。
JavaScript
POST https://{WebHookBaseUrl}/game/create
CreateGameリクエスト
Name | Type | Example | Description |
---|---|---|---|
AppId |
string |
d1f67eec-51fb-45c1 |
The Photon AppId. |
AppVersion |
string |
1.0-live |
ルームまたはゲームセッションの作成時に使用されるアプリバージョンです。 |
Region |
string |
eu |
ルームまたはゲームセッションが作成されたゲームサーバーのリージョンコードです。. |
Cloud |
string |
1 |
そのゲームサーバーが稼働しているCloud Id です。 |
UserId |
string |
db757806-8570-45aa |
ルームまたはゲームセッションを作成したクライアントのUserId です。 |
AuthCookie |
Dictionary<string, object> |
db757806-8570-45aa |
バックエンドによって設定されたPhotonのカスタム認証クッキーです。 |
RoomName |
string |
e472a861-a1e2-49f7 |
ルームまたはゲームセッションの名前です. |
GameId |
string |
0:eu:e472a861-a1e2-49f7 |
GameId は、 {Cloud:}{Region:}RoomName で構成される一意のIDです。レスポンスによって上書きされることがあります。 |
EnterRoomParams |
EnterRoomParams |
JSON: EnterRoomParam セクションをご覧ください |
クライアントから送信されたPhotonのルームまたはゲームセッションのオプションです |
Jsonの例:
JSON
{
"AppId": "d1f67eec-51fb-45c1",
"AppVersion": "1.0-live",
"Region": "eu",
"Cloud": "1",
"UserId": "db757806-8570-45aa",
"AuthCookie": {
"Secret": "**********"
}
"RoomName": "e472a861-a1e2-49f7",
"GameId": "0:eu:e472a861-a1e2-49f7",
"EnterRoomParams": {
"RoomOptions": {
"IsVisible": true,
"IsOpen": true
}
}
}
HTTP応答コード
Name | Type | Description |
---|---|---|
200 OK |
CreateGame応答 |
ルームまたはゲームセッションの作成は開始されますが、レスポンスの設定データによってクライアントから送信されたデータが上書きされます。 |
400 Bad Request |
WebhookError |
ルームまたはゲームセッションの作成は許可されず、キャンセルされます。クライアントはエラーを受け取ります。 |
CreateGame応答
Name | Type | Description |
---|---|---|
GameId |
string |
後続のウェブリクエストで使用される `GameId ` を上書きします。値は ` null ` もしくは省略可能です。 |
EnterRoomParams |
EnterRoomParams |
作成時に選択したルームオプションを強制適用します。 JSONオブジェクトには、上書きしたいメンバーだけを含める必要があり、すべてのメンバーを含める必要はありません。 最初のオプションは、`EnterRoomParams`を送信することで保護されます。ほとんどの設定は、クライアントがPhotonのルームプロパティを送信して変更することが可能です。これを防ぐには、Photonダッシュボードの `BlockRoomProperties`設定を有効にしてください。 値は ` null ` もしくは省略可能です。 |
Name | Type | Description |
---|---|---|
SessionConfig |
SessionConfig |
Return a SessionConfig object that is used by the game. Game configs sent by clients will be ignored. |
RuntimeConfig |
RuntimeConfig |
Return a RuntimeConfig object that is used by the game. Game configs sent by clients will be ignored. |
RuntimePlayer |
RuntimePlayer |
Return a RuntimePlayer object that will be used for the client that created this room/session.This only overwrites the first AddPlayer data sent for player slot 0 . MaxPlayerSlots should be set to 1 . |
MaxPlayerSlots |
int |
The maximum number of player slots this client can acquire:0 = only spectating1..255 = specific number-1 = unlimitedIf this response is sent but this value is not set MaxPlayerSlots will default to 1.Players requesting an invalid player slot number or more slots than allowed will be disconnected. |
SnapshotsBlocked |
bool |
This player will not be selected for sending game snapshots to other players if there are other clients available. |
StartPropertyBlockedTimeSec |
int |
Minimum delay in seconds before starting Quantum inside a room after its creation, ensuring players have enough time to join. A value greater than zero activates this feature. |
StartPropertyForcedTimeSec |
int |
Maximum delay in seconds before starting Quantum inside a room after its creation. Exceeding this time auto-activates "StartQuantum" if not already set. A value greater than zero activates this feature. |
HideRoomAfterStartSec |
int |
Number of seconds after which the room will be hidden from public listings once Quantum starts within the room. A value greater than zero activates this feature. |
CloseRoomAfterStartSec |
int |
Number of seconds after which the room will be closed following the start of Quantum inside the room, preventing new players from joining. A value greater than zero activates this feature. |
Json Example:
JSON
{
"AppId": "d1f67eec-51fb-45c1",
"GameId": "0:eu:db757806-8570-45aa",
"EnterRoomParams": {
"RoomOptions": {
"IsVisible": true,
"IsOpen": true
}
},
"SessionConfig": {
"PlayerCount": 8,
"ChecksumCrossPlatformDeterminism": false,
"UpdateFPS": 30
},
"RuntimeConfig": {
"Map": {
"Id": {
"Value": 94358348534
}
}
},
"RuntimePlayer": {
"Name": "player1"
},
"MaxPlayerSlots": 2,
"SnapshotsBlocked": true
}
JoinGame
JoinGame
Webhookは、クライアントが既存のルームやゲームセッションに参加する前に送信されます。
参加を許可する場合は200
を返し、キャンセルする場合は400
を返してください。
このWebhookを有効にするには、PhotonアプリIDダッシュボードでWebHookBaseUrl
とWebHookEnableOnJoin
を設定する必要があります。
JavaScript
POST https://{WebHookBaseUrl}/game/join
JoinGameリクエスト
Name | Type | Example | Description |
---|---|---|---|
AppId |
string |
d1f67eec-51fb-45c1 |
Photon AppId |
GameId |
string |
0:eu:db757806-8570-45aa |
一意のGameId |
UserId |
string |
db757806-8570-45aa |
Photon UserId |
AuthCookie |
Dictionary<string, object> |
db757806-8570-45aa |
バックエンドによって設定されたPhotonのカスタム認証クッキーです。 |
Jsonの例:
JSON
{
"AppId": "*******************",
"GameId": "0:eu:db757806-8570-45aa",
"UserId": "db757806-8570-45aa",
"AuthCookie": {
"Secret": "**********"
}
}
HTTP応答コード
Name | Type | Description |
---|---|---|
200 OK |
JoinGame Response |
クライアントがルームに参加します。 |
400 Bad Request |
WebhookError |
ルームへの参加は失敗します。 |
JoinGame応答
Name | Type | Description |
---|---|---|
RuntimePlayer | RuntimePlayer |
Return a RuntimePlayer object that will be used for the client that created this room/session.This only overwrites the first AddPlayer data sent for player slot 0 . MaxPlayerSlots should be set to 1 . |
MaxPlayerSlots | int |
The maximum number of player slots this client can acquire:0 = only spectating1..255 = specific number-1 = unlimitedIf this response is send but this value is not set MaxPlayerSlots will default to 1.Players requesting an invalid player slot number or more slots than allowed will be disconnected. |
Json Example:
JSON
{
"RuntimePlayer": {
"Name": "player1"
},
"MaxPlayerSlots": 1
}
Hint
Rather use AddPlayer
to return the RuntimePlayer
data, because its request will includes a RuntimePlayer
client object sent by the client.
Also consider using the CreateGame
response to reserve player slots for users (if they are already known at that time).
LeaveGame
LeaveGame
Webhookは、クライアントが既存のルームまたはゲームセッションを離れた後に送信されます。
このWebhookを有効にするには、PhotonアプリIDダッシュボードでWebHookBaseUrl
とWebHookEnableOnLeave
を設定してください。
JavaScript
POST https://{WebHookBaseUrl}/game/leave
LeaveGameリクエスト
Name | Type | Example | Description |
---|---|---|---|
AppId |
string |
d1f67eec-51fb-45c1 |
Photon AppId |
GameId |
string |
0:eu:db757806-8570-45aa |
一意のGameId |
UserId |
string |
db757806-8570-45aa |
Photon UserId |
ActorNr |
int |
db757806-8570-45aa |
Photonサーバーが割り当てるアクター番号で、クライアントごとにインクリメントされるランタイムIDです。 |
AuthCookie |
Dictionary<string, object> |
db757806-8570-45aa |
Photon UserId |
IsInactive |
bool |
db757806-8570-45aa |
プレイヤーがルームを離れたが、Player TTLが設定されている場合などで、まだ非アクティブとしてマークされているときに`true`に設定されます。この状態では、追加の`LeaveGame`リクエストが続けて送信されることがあります。 |
Jsonの例:
JSON
{
"AppId": "*******************",
"GameId": "0:eu:db757806-8570-45aa",
"UserId": "db757806-8570-45aa",
"ActorNr": 1,
"AuthCookie": {
"Secret": "**********"
},
"IsInactive": false
}
HTTP Response Codes
Name | Type | Description |
---|---|---|
200 OK |
LeaveGame Response |
受信の確認のみ。 |
400 Bad Request |
WebhookError |
エラーが無視されます。Photon Cloudにログされるだけです。 |
LeaveGameレスポンス
Jsonの例:
JSON
{
// empty
}
CloseGame
CloseGame
webhookは、クライアント全員が退出した後、ルーム/ゲームセッションが閉じられると送信されます。
Photonダッシュボード上でWebHookBaseUrl
およびWebHookEnableOnClose
の設定が必須です。
JavaScript
POST https://{WebHookBaseUrl}/game/close
CloseGameリクエスト
Name | Type | Example | Description |
---|---|---|---|
AppId |
string |
d1f67eec-51fb-45c1 |
The Photon AppId |
GameId |
string |
0:eu:db757806-8570-45aa |
Unique game id |
CloseReason |
int (CloseReason ) |
0 |
The reason why this room/session has been closed. |
Json Example:
JSON
{
"GameId": "0:eu:db757806-8570-45aa",
"CloseReason": 0
}
HTTP応答コード
Name | Type | Description |
---|---|---|
200 OK |
Confirmation of receipt. |
CloseReason
Name | Value | Description |
---|---|---|
Ok |
0 |
Session was closed without errors. |
FailedOnCreate |
1 |
Session was closed because it failed to Create. |
GameConfigs
The GameConfigs
webhook is sent when a player sent a StartRequest
operation attached with the game configs RuntimeConfig
and SessionConfig
. Both config files are attached to the request body as Json objects.
This webhook is only send once per room upon the first arrival of any clients start operation.
Requires WebHookBaseUrl
and WebHookEnableGameConfigs
to be set on the Photon dashboard.
JavaScript
POST https://{WebHookBaseUrl}/game/configs
GameConfigs Request
Name | Type | Example | Description |
---|---|---|---|
AppId | string |
d1f67eec-51fb-45c1 |
The Photon AppId |
GameId | string |
0:eu:db757806-8570-45aa |
Unique game id |
UserId | string |
db757806-8570-45aa |
Photon UserId |
ActorNr | int |
db757806-8570-45aa |
The Photon actor number, a incrementing runtime id for clients. |
RuntimeConfig | RuntimeConfig |
{ "Level": 1 } |
The RuntimeConfig object sent by the client to the plugin. Can be null. |
SessionConfig | SessionConfig |
{ "PlayerCount": 8, .. } |
The SessionConfig object sent by the client to the plugin. Can be null. |
AuthCookie | Dictionary<string, object> |
db757806-8570-45aa |
The Photon custom authentication cookie set by the backend. |
Json Example:
JSON
{
"AppId": "d1f67eec-51fb-45c1",
"GameId": "0:eu:db757806-8570-45aa",
"UserId": "db757806-8570-45aa",
"ActorNr": 1,
"RuntimeConfig": {
"Map": {
"Id": {
"Value": 94358348534
}
}
},
"SessionConfig": {
"PlayerCount": 8,
"ChecksumCrossPlatformDeterminism": false,
"LockstepSimulation": false,
//..
},
"AuthCookie": {
"Secret": "**********"
}
}
HTTP Response Codes
Name | Type | Description |
---|---|---|
200 OK | GameConfigs Response |
The game start sequence can continue. Game configs attached to response should be overwritten. |
400 Bad Request | WebhookError |
The game will be terminated and all clients are disconnected. |
GameConfigs Response
Both objects on the response can be null
to accept the configs that the client sent. Otherwise they will be overwritten.
Name | Type | Description |
---|---|---|
RuntimeConfig | RuntimeConfig |
The RuntimeConfig object to overwrite the one the client sent. |
SessionConfig | SessionConfig |
The SessionConfig object to overwrite the one the client sent. |
Json Example:
JSON
{
"RuntimeConfig": {
"Map": {
"Id": {
"Value": 94358348534
}
}
},
"SessionConfig": {
"PlayerCount": 8,
"ChecksumCrossPlatformDeterminism": false,
"LockstepSimulation": false,
//..
}
}
AddPlayer
The AddPlayer
webhook is sent when a client tries to add a player to the Quantum online game using the AddPlayer
operation.
Adding a player to the online game can still fail after this webhook returns when no player slot is free then. Use the PlayerAdded
webhook to track the player online status.
Requires WebHookBaseUrl
and WebHookEnableAddPlayer
to be set on the Photon dashboard.
JavaScript
POST https://{WebHookBaseUrl}/player/add
AddPlayer Request
Name | Type | Example | Description |
---|---|---|---|
AppId | string |
d1f67eec-51fb-45c1 |
The Photon AppId |
GameId | string |
0:eu:db757806-8570-45aa |
Unique game id |
UserId | string |
db757806-8570-45aa |
Photon UserId or ClientId |
ActorNr | int |
db757806-8570-45aa |
The Photon actor number, a incrementing runtime id for clients. |
PlayerSlot | int |
0 |
Player slot requested. Usually is 0. |
RuntimePlayer | RuntimePlayer |
{ "Foo": 222 } |
The RuntimePlayer object sent by the client to the plugin. Can be null. |
AuthCookie | Dictionary<string, object> |
db757806-8570-45aa |
The Photon custom authentication cookie set by the backend. |
Json Example:
JSON
{
"AppId": "d1f67eec-51fb-45c1",
"GameId": "0:eu:db757806-8570-45aa",
"UserId": "db757806-8570-45aa",
"ActorNr": 1,
"PlayerSlot": 0,
"RuntimePlayer": {
"Name": "player1"
},
"AuthCookie": {
"Secret": "**********"
}
}
HTTP Response Codes
Name | Type | Description |
---|---|---|
200 OK | AddPlayer Response |
The client can add a player to the selected player slot and optionally received a RuntimePlayer object from the backend. |
400 Bad Request | WebhookError |
The client cannot add the player and will receive an error protocol message and callback: OnLocalPlayerAddFailed . |
AddPlayer Response
Name | Type | Description |
---|---|---|
RuntimePlayer | object |
The RuntimePlayer object to overwrite the RuntimePlayer that the client sent. If null the clients RuntimePlayer will be accepted.
|
Json Example:
JSON
{
"RuntimePlayer": {
"Name": "player1"
}
}
PlayerAdded
The PlayerAdded
webhook is send after a client successfully added a player to the online game.
Requires WebHookBaseUrl
and WebHookEnablePlayerAdded
to be set on the Photon dashboard.
JavaScript
POST https://{WebHookBaseUrl}/player/added
PlayerAdded Request
Name | Type | Example | Description |
---|---|---|---|
AppId | string |
d1f67eec-51fb-45c1 |
The Photon AppId |
GameId | string |
0:eu:db757806-8570-45aa |
Unique game id |
UserId | string |
db757806-8570-45aa |
Photon UserId or ClientId |
ActorNr | int |
db757806-8570-45aa |
The Photon actor number, a incrementing runtime id for clients. |
PlayerSlot | int |
0 | The (local) player slot that the client reserved. |
Player | int |
21 | The (global) Player id that the client received. |
AuthCookie | Dictionary<string, object> |
db757806-8570-45aa |
The Photon custom authentication cookie set by the backend. |
Json Example:
JSON
{
"AppId": "d1f67eec-51fb-45c1",
"GameId": "0:eu:db757806-8570-45aa",
"UserId": "db757806-8570-45aa",
"ActorNr": 1,
"PlayerSlot": 0,
"Player": 21,
"AuthCookie": {
"Secret": "**********"
}
}
HTTP Response Codes
Name | Type | Description |
---|---|---|
200 OK | Confirmation of receipt. |
PlayerRemoved
The PlayerRemoved
webhook is sent when a client was removed from the online game.
Requires WebHookBaseUrl
and WebHookEnablePlayerRemoved
to be set on the Photon dashboard.
JavaScript
POST https://{WebHookBaseUrl}/player/removed
PlayerRemoved Request
Name | Type | Example | Description |
---|---|---|---|
AppId | string |
d1f67eec-51fb-45c1 |
The Photon AppId |
GameId | string |
0:eu:db757806-8570-45aa |
Unique game id |
UserId | string |
db757806-8570-45aa |
Photon UserId or ClientId |
ActorNr | int |
db757806-8570-45aa |
The Photon actor number, a incrementing runtime id for clients. |
PlayerSlot | int |
0 | The (local) player slot. |
Player | int |
21 | The (global) Player id. |
Reason | int |
0 | The reason why the player was removed from the game. 0 = Requested 1 = ClientDisconnected 2 = Error |
AuthCookie | Dictionary<string, object> |
db757806-8570-45aa |
The Photon custom authentication cookie set by the backend. |
Json Example:
JSON
{
"AppId": "d1f67eec-51fb-45c1",
"GameId": "0:eu:db757806-8570-45aa",
"UserId": "db757806-8570-45aa",
"ActorNr": 1,
"PlayerSlot": 0,
"Player": 21,
"Reason": 0,
"AuthCookie": {
"Secret": "**********"
}
}
HTTP Response Codes
Name | Type | Description |
---|---|---|
200 OK | Confirmation of receipt. |
GameResult
Using the GameResult
Quantum event in the simulation will trigger the upload of a GameResult instance by clients to the Quantum server once per game.
The results are aggregated and forwarded as the GameResult
webhook when the game/room is closed. Because lingering clients and RoomTTL
can prolong closing the room, there can be a delay between the game ending and the result webhook.
Requires WebHookBaseUrl
and WebHookEnableGameResult
to be set on the Photon dashboard.
Note:
- The
GameResult
webhook supports both standard JSON format and binary payloads using base64 encoding.- Dictionaries are not supported, due to Unity serialization limitations. Quantum relies on Unity's built-in serialization system, which does not support
Dictionary<,>
types. These fields will be ignored or cause deserialization failures if present.
Requires WebHookBaseUrl
and WebHookEnableGameResult
to be set on the Photon dashboard.
If the server is running the simulation the webhooks are executed immediately from the server simulation and can be used as a reliable and trusted source of game results.
JavaScript
POST https://{WebHookBaseUrl}/game/result
Replays
The game result can also be used inside a replay by registering to EventGameResult
.
C#
var eventDispatcher = new EventDispatcher();
eventDispatcher.SubscribeManual((EventGameResult e) => {
if (e.Game?.Session != null) {
// Handle result and stop replay
}
});
GameResult Request
Name | Type | Example | Description |
---|---|---|---|
AppId | string |
d1f67eec-51fb-45c1 |
The Photon AppId |
GameId | string |
0:eu:db757806-8570-45aa |
Unique game id |
Results | GameResultInfo[] |
see below | The aggregated game results |
Json Example:
JSON
{
"AppId": "d1f67eec-51fb-45c1",
"GameId": "0:eu:db757806-8570-45aa",
"Results": [
{
"Clients": [
{
"UserId": "FJEH43FL56FSDR",
"Players": [
0
],
"GameTime": 63.3636703
}
],
"Result": {
"$type": "Quantum.GameResult, Quantum.Simulation",
"Frame": 12010
"Winner": 2
},
"IsServerResult": false
}
],
"UserId": "0"
}
HTTP Response Codes
Name | Description |
---|---|
200 OK | Confirmation of receipt |
GameResultInfo
Name | Type | Description |
---|---|---|
Result | GameResult |
The game specific game result Json object that the listed clients sent |
Clients | GameResultClientInfo[] |
The list of clients that generated this result |
IsServerResult | bool |
Has this result been generated by server simulation |
GameResultClientInfo
Name | Type | Description |
---|---|---|
UserId | string |
The Photon user id |
Players | int[] |
The list of players that this user controls |
GameTime | float |
The timestamp when the result reached the server |
ReplayStart
The ReplayStart
webhook is sent when the simulation and the input recording is starting on the server. It's is a trusted source for capturing the game replay directly from the server instead of relying on clients to send it to a developers backend.
This webhook has to be answered with the ReplayStartResponse
which can signal the replay streaming to be skipped for this particular game session.
A response has to be received by the Quantum server before it is sending its first replay slice or the replay recording will be canceled.
Requires WebHookBaseUrl
and WebHookEnableReplay
to be set on the Photon dashboard.
JavaScript
POST https://{WebHookBaseUrl}/replay/start
ReplayStart Request
Name | Type | Description |
---|---|---|
AppId | string |
The Photon AppId. |
AppVersion | string |
The AppVersion used when creating the room/game session. |
Region | string |
The Region code of the Game Server that the room/game session was created in. |
Cloud | string |
The Cloud Id of that the Game Server is running on. |
RoomName | string |
The room/game session Name. |
GameId | string |
A unique GameId which is composed of {Cloud:}{Region:}RoomName . |
SessionConfig | SessionConfig |
The SessionConfig that the simulation started with. |
RuntimeConfig | byte[] |
The GZipped Json of the RuntimeConfig that the simulation started with. |
Json Example:
JSON
{
"AppId": "d1f67eec-51fb-45c1",
"AppVersion": "1.0-live",
"Region": "eu",
"Cloud": "0:",
"RoomName": "1.2-party-2349535735",
"GameId": "0:eu:e472a861-a1e2-49f7",
"SessionConfig": { },
"RuntimeConfig": "H4sIAAAAAAAACnWNPQvCMBCG/4ocjkWuye
X6sXZycNCCe8AogSYtNBlK6X/3UHQR4Zb35X2eW2GflslBC+ds
Y8rhcMkx+eC6Md79o9h96t6HPNjkxwgF9M7doMUCTnaCdoWjpB
WudshiUkxYsVHacE11KWe2TZiv4K3+4YjQkECKNJcVMuoXtszJ
hfkPI1tUVc1sqFGN1g3Kr+0J+3ktedUAAAA="
}
HTTP Response Codes
Name | Type | Description |
---|---|---|
200 OK | ReplayStart Response |
The replay streaming can start or be disabled when the Skip property is set. |
400 Bad Request | WebhookError |
In this case an error is logged on the server and the replay streaming is stopped. |
ReplayStart Response
Name | Type | Description |
---|---|---|
Skip | bool |
The replay streaming is disabled for this game session. |
Json Example:
JSON
{
"Skip": true
}
ReplayChunk
The ReplayChunk
webhook is sent in intervals and it contains the delta compressed input history of a part of the simulation.
Requires WebHookBaseUrl
and WebHookEnableReplay
to be set on the Photon dashboard.
JavaScript
POST https://{WebHookBaseUrl}/replay/chunk
There are additional dashboard variables that configure the replay input streaming.
Dashboard Variable | Type | Description | Default |
---|---|---|---|
WebHookReplayUseBinaryRequests | bool |
The web request are not send as JSON content but as binary data. | false |
WebHookReplayUseCompression | bool |
The input data on the chunks is GZip compressed. | false |
WebHookReplaySendIntervalInSec | int |
The chunk send interval in seconds (min = 2, max = 40). | 20 |
ReplayChunk Request
If WebHookReplayUseBinaryRequests
is selected, then the following properties are part of the web request Headers
instead of a JSON body. The body then will include the binary Input
.
Name | Type | Description |
---|---|---|
AppId | string |
The Photon AppId |
GameId | string |
The game id to identify the replay chunk. |
ChunkNumber | int |
The incrementing chunk number. |
IsLast | bool |
A flag that indicates that the last chunk has been send. Usually when a room closes. |
LastTick | int |
The oldest tick of input on this chunk. |
TickCount | int |
The number of ticks of input on this chunk. |
TickCountTotal | int |
The total incrementing number of ticks in the whole replay. |
IsCompressed | bool |
A flag indicating the input is GZip compressed. |
Input | byte[] |
The binary delta compressed input that needs to be appended to the complete input stream for this replay.
The input for each tick has a leading int describing the data length. It can be stored in the ReplayFile.InputHistoryRaw field to be readable with the QuantumRunnerLocalReplay script in Unity. |
Json Example:
JSON
{
"AppId": "d1f67eec-51fb-45c1",
"GameId": ":eu:e472a861-a1e2-49f7",
"ChunkNumber": 0,
"IsLast": false,
"LastTick": 302,
"TickCount": 243,
"TickCountTotal": 243,
"IsCompressed": false,
"Input": "JQAAADwAAAAIAAMKFsCUwYDggOB/UCAAAPgfDMhgEoAHA////4PRBwATAAAAPQAAAAgAA2PaSK"
}
HTTP Response Codes
Name | Type | Description |
---|---|---|
200 OK | Confirmation of receipt. | |
400 Bad Request | WebhookError |
In this case an error is logged on the server and the replay streaming is stopped. |
WebhookError
Name | Type | Description |
---|---|---|
Status |
int |
HTTPステータスコード |
Error |
string |
エラー名 |
Message |
string |
エラーメッセージ |
Jsonの例:
JSON
{
"Status": 400,
"Error": "PlayerNotAllowed",
"Message": "LoremIpsum"
}
Quantum Classes
RuntimeConfig
Quantum 3 runtime configuration files RuntimeConfig
and RuntimePlayer
are uploaded by the clients using Json serialization. This way it is possible to send configurations to the Quantum public cloud game servers while it does not know the implementation and serialization details.
When RuntimeConfig
or RuntimePlayer
are used in a webhook response they need to be complete because the configs send by clients are completely replaced.
Json data sent by the custom backend has to be deterministically deserializable on every client.
Quantum internal classes usually operate with fields, make sure that the Json serialization and deserialization code needs to IncludeFields = true
and IgnoreReadOnlyProperties = true
.
A simple example of the RuntimeConfig
class. Additionally to the partial declaration the base class adds a couple properties as well (Seed, Map, SimulationConfig, SystemsConfig).
The $type
property is required for deserialization on the standalone or custom plugin.
C#
namespace Quantum {
public partial class RuntimeConfig {
public int GameMode;
}
}
Json Example:
JSON
{
"$type": "Quantum.RuntimeConfig, Quantum.Simulation",
"GameMode": 1,
"Seed": 0,
"Map": {
"Id": {
"Value":2640765235684814815
}
},
"SimulationConfig": {
"Id": {
"Value":440543562436170603
}
},
"SystemsConfig": {
"Id": {
"Value":2430278665492933905
}
}
}
RuntimePlayer
C#
namespace Quantum {
public partial class RuntimePlayer {
public AssetRef<GearConfig> Loadout;
}
}
Json Example:
JSON
{
"$type":"Quantum.RuntimePlayer, Quantum.Simulation",
"Loadout": {
"Id": {
"Value": 440543562436170603
}
},
"PlayerAvatar": {
"Id": {
"Value": 2430278665492933905
}
},
"PlayerNickname": "foo"
}
SessionConfig
SessionConfig
is the abbreviation of the DeterministicSessionConfig
class.
When a SessionConfig
is returned by an webhook it needs to be complete because single values are not replaced.
The current SessionConfig
asset can be exported in Unity using this menu entry:
Unity Editor > Quantum > Export > SessionConfig (Json)
When serializing the class on netcoreapp3.1
either use Newtonsoft
or use DeterministicSessionConfigJsonConverter
for Text.Json
. Because "including fields" is a feature of net5
.
Json Example:
JSON
{
"PlayerCount": 8,
"ChecksumCrossPlatformDeterminism": false,
"LockstepSimulation": false,
"InputDeltaCompression": true,
"UpdateFPS": 60,
"ChecksumInterval": 60,
"RollbackWindow": 60,
"InputHardTolerance": 8,
"InputRedundancy": 3,
"InputRepeatMaxDistance": 10,
"SessionStartTimeout": 1,
"TimeCorrectionRate": 4,
"MinTimeCorrectionFrames": 1,
"MinOffsetCorrectionDiff": 1,
"TimeScaleMin": 100,
"TimeScalePingMin": 100,
"TimeScalePingMax": 300,
"InputDelayMin": 0,
"InputDelayMax": 60,
"InputDelayPingStart": 100,
"InputFixedSizeEnabled": true,
"InputFixedSize": 24
}
GameResult Event
The GameResult
class can be extended by adding fields using the partial class declaration inside the GameResult.User.cs
script. It will be Json serialized on the client and send to the Quantum server.
C#
namespace Quantum {
public partial class GameResult {
public int Winner;
}
}
Json Example:
JSON
{
"$type":"Quantum.GameResult, Quantum.Simulation",
"Frame": 200,
"Winner": 2
}
The game result event can be invoked once per game by each client, which is triggered from inside the simulation by calling the GameResult Quantum event. The actual webhook is launched when the room is disbanded and closed.
C#
f.Events.GameResult(new GameResult { Winner = 3 });
When running an enterprise Photon Quantum cloud with server simulation this will be transparently send by the server for a trusted source of game results.
Photon Realtime Classes
EnterRoomParams
この定義は、Photon RealtimeのEnterRoomParams
クラスに似せて設計されています。CreateGame
Webhookで設定可能なすべてのオプションを含んでいます。JSONレスポンスを作成する際は、すべてのメンバーが任意であり、nullまたは未設定にすることも可能です。
Name | Type | Description |
---|---|---|
RoomOptions |
RoomOptions |
RoomOptionsオブジェクト |
ExpectedUsers |
string[] |
ルームまたはセッションに参加を許可するUserIds の一覧です(ルームを作成したユーザーに加えて)。もし MaxPlayers が記載されたExpectedUsers の数より大きい場合は、未予約の枠に任意のプレイヤーが参加して埋めることができます。これは RoomJoin() のみに有効で、JoinRandom() には適用されません。 |
Jsonの例:
JSON
{
"RoomOptions": {
"IsVisible": true,
"IsOpen": true,
"MaxPlayers": 8,
"PlayerTtl": null,
"EmptyRoomTtl": 10000,
"CustomRoomProperties": {
"Foo": "bar",
"PlayerClass": 1
},
"CustomRoomPropertiesForLobby": [
"Foo"
],
"SuppressRoomEvents": null,
"SuppressPlayerInfo": null,
"PublishUserId": null,
"DeleteNullProperties": null,
"BroadcastPropsChangeToAll": null,
"CleanupCacheOnLeave": null,
"CheckUserOnJoin": null
},
"ExpectedUsers": [
"A",
"B",
"C"
]
}
RoomOptions
すべての値はnull許容型であり、Quantumサーバーに返信する際にnull
に設定したり、省略したりすることが可能です。その場合、このレスポンスは該当するルームプロパティを変更せず、デフォルトの値のままか、ルーム作成時にクライアントが送信した値が維持されます。
Name | Type | Description |
---|---|---|
IsVisible |
bool |
このルームがPhotonのマッチメイキングにリストされるかどうかを定義します。 |
IsOpen |
bool |
このルームに他のクライアントが参加できるかどうかを定義します。 |
MaxPlayers |
byte |
任意の時点でルーム内に入れる最大プレイヤー数です。0は「制限なし」を意味します。 |
PlayerTtl |
int |
ルーム内の「アクター」の生存時間(TTL)をミリ秒単位で設定します。クライアントが切断された場合、このアクターは最初に非アクティブとなり、指定されたタイムアウト後に削除されます。 |
EmptyRoomTtl |
int |
最後のプレイヤーが退室した後のルームの生存時間(TTL)をミリ秒単位で設定します。これは、プレイヤーが近いうちに再参加する場合にルームをメモリ内に保持しておくためのものです。 |
CustomRoomProperties |
|
ルーム作成時に設定されるカスタムプロパティです。 |
CustomRoomPropertiesForLobby |
string[] |
ロビーにリストされるカスタムルームプロパティを定義します。 これらのプロパティの値の型は bool , byte , short , int , long または string である必要があります。最大プロパティ数は 3 です。 文字列値の最大長は 64 文字です。 キーの制限は、Photonダッシュボードの設定AllowedLobbyPropertiesによっても適用可能です。 |
SuppressRoomEvents |
bool |
サーバーに対して、参加および退出するプレイヤーのルームイベントをスキップするよう指示します。 デフォルトは false です。 |
SuppressPlayerInfo |
bool |
サーバー側での参加と退出のイベントおよびルーム内のプロパティブロードキャストを無効にします(通信量を最小化するため)。 デフォルトは false です。 |
PublishUserId |
bool |
プレイヤーのUserIdsをルーム内で「公開」するかどうかを設定します。 これは、FindFriendsの機能を利用したり、プレイヤー同士が別のゲームで一緒にプレイしたい場合に役立ちます。 デフォルトは false です。 |
DeleteNullProperties |
bool |
オプションとして、値に null を割り当てると、そのプロパティが削除されます。デフォルトは false です。/td>
|
PlayFab
PlayFabと連携させるには、WebHookIntegration
ダッシュボード変数を追加し、その値をPlayFab
に設定してください。
- パス内のすべてのスラッシュ(
/
)はアンダースコア(_
)に置き換えられます。例:game/create
→game_create
- すべてのWebhookリクエストには、
WebHooksConfig.AppId
によって制御されるAppId
プロパティが自動的に追加されます(欠落している場合)。 - すべてのWebhookリクエストには、
UserId
プロパティが自動的に追加され、欠落している場合は"0"
が設定されます。 - Webhookのレスポンスは、以下のJson結果ボディを処理し、
ResultCode
が0以外の場合にWebhookを失敗とみなします。エラー時には、Message
がWebHookError.Message
にコピーされます。
JSON
{
"ResultCode": 0,
"Message": "success"
}
Photon CloudのWebリクエスト制限
デフォルトでは、PhotonサーバーはHTTPリクエストを直列に管理し、現在のリクエストが完了するまで新たなリクエストは開始されません。新しいリクエストはキューに追加されます。この制限は各ルームごとに適用されます。
このため、OnJoinやAddPlayerのWebhookを使用している場合、高いプレイヤー数やPhotonクラウドとカスタムバックエンド間のラウンドトリップタイムが長い場合に、予期しない待ち時間が発生する可能性があります。
並列リクエストはエンタープライズクラウドで有効にでき、また、公開クラウドアプリ向けにも選択制の対応を検討中です。
その他の制限は以下の通りです。
HttpRequestTimeout
: 30000LimitHttpResponseMaxSize
: 200000MaxQueuedRequests
: 5000