> For the complete documentation index, see [llms.txt](/llms.txt)

# GS2-Realtime

リアルタイム通信機能




ゲームプレイヤー同士での対戦機能を実現するために、低レイテンシーかつ高頻度で通信する場合に利用できる機能です。

GS2 では一般的にAPIリクエスト回数に対して料金が発生しますが、このサービスについてはゲームサーバーが起動すれば、
そのゲームサーバーの起動時間と、通信容量に対して費用が発生し、通信回数に対しては費用が発生しません。

```mermaid
graph TD
  Match["GS2-Matchmaking で<br/>ロビーを成立"] --> Want["RoomWant でルーム要求"]
  Want -- ホットスタンバイから割り当て --> Warm["Warm Start (1〜3秒)"]
  Want -- 新規起動 --> Cold["Cold Start (40〜60秒)"]
  Warm --> Connect["プレイヤーが接続"]
  Cold --> Connect
  Connect --> Play["パケットリレーで対戦中通信"]
  Play -- 1分間無通信または3時間経過 --> Shutdown["ルーム終了"]
```

## サーバータイプ

現在、GS2-Realtime はパケットリレー機能のみを提供しています。
これはゲームサーバーにメッセージを送信すると、そのメッセージが他のプレイヤーにブロードキャストされる機能を基本として
プレイヤーIDを指定して、指定したプレイヤーにメッセージを届ける機能のみを有します。

RPCやオブジェクト同期といった機能はSDKには含まれておらず、単純なバイナリデータの送受信のみを行えます。
ペイロードのバイナリエンコーディングはアプリケーション側の責務となるため、Protocol Buffers / FlatBuffers / MessagePack といった任意のエンコーディングを採用できます。

### Unreal Engine Dedicated Server ホスティング

開発者が Unreal Engine でビルドした Dedicated Server をホスティングできるようにすることを検討しています。
この機能の提供時期については未定です。

有償サポート契約をしたうえで開発を勧められる、強いニーズがあればスケジュールを調整できますので、ご相談ください。

## サーバースペック

サーバーの性能を設定できます。性能によって1分あたりの利用料金に差が生じます。
最も安い realtime1.nano で 8人プレイヤーが1秒間に3回メッセージを送り合えることを確認しています。

検討中の Unreal Engine Dedicated Server ホスティング では、要求スペックがこれより高くなることが予想されます。
開発効率ではなくコスト効率が最も重要なプロジェクトでは、Unreal Engine Dedicated Server の利用は推奨できません。

サーバースペックは Namespace ごとに設定し、`serverSpec` フィールドに `realtime1.nano` のような識別子を指定します。

## ライフサイクル

ゲームサーバーは起動リクエストを受け付けてから手配が開始されます。

このとき、頻繁に起動リクエストが発生するゲームサーバーについては、GS2がホットスタンバイを用意します。
そのため、起動リクエストを受け付けた直後に割り当てが行われることが期待できますが、頻繁に起動リクエストが発生しない小規模なゲームでは起動リクエストから実際の割り当てまで時間がかかります。

ホットスタンバイからの割り当てを行うケースをウォームスタート、新しくサーバーを起動して割り当てるケースをコールドスタートと呼んでいます。
コールドスタート時の割り当てに必要な目安の時間は40秒〜60秒程度、ウォームスタート時の割り当てに必要な時間は1秒〜3秒を想定してください。

頻繁な起動リクエストが発生しない規模のタイトルで、コールドスタートの時間が許容できない場合
毎月固定費用が発生する前提でホットスタンバイを提供できます。ホットスタンバイの契約は5台から契約を受け付けています。

ホットスタンバイを契約していたり、頻繁な起動リクエストが発生している状況でもコールドスタートが発生しないことを保証できません。
ホットスタンバイを用意するより早くサーバーの起動リクエストを出したり、ゲームサーバーのバージョンアップ時にはコールドスタートが発生する可能性があります。
そのため、ワーストケースとしてコールドスタートが発生する状況を念頭にシステムを設計してください。

### スタートの種類

| 種類 | 所要時間 | 説明 |
| -- | -- | -- |
| ウォームスタート | 1〜3秒 | ホットスタンバイから即時割り当て |
| コールドスタート | 40〜60秒 | 新しくサーバープロセスを起動 |

### ルームの終了条件

起動されたルームは以下の条件で終了されます。

- ルーム作成後 **5分間** 誰も接続に来なかった場合
- ルームに参加する全プレイヤーから **1分間** 無通信状態が続いた場合
- ルームの最大起動時間である **3時間** が経過した場合

加えて、明示的に `RoomShutdown` を呼び出すことで、ルームを即時終了させることもできます。

なお、ホットスタンバイのルームにも同様の終了処理が適用されますが、ホットスタンバイの起動時間は利用料金に加算されません。

## ルームへの接続

GS2-Realtime は以下のフローで接続します。

```mermaid
sequenceDiagram
  participant Player
  participant Realtime as GS2-Realtime
  participant Server as GameServer
  Player ->> Realtime: Room(roomName).Model()
  Realtime -->> Player: IpAddress / Port / EncryptionKey
  Player ->> Server: RelayRealtimeSession.ConnectAsync()
  Server -->> Player: 接続完了
  Note over Player,Server: 以降はゲームサーバーと直接 WebSocket 通信
```

接続情報は以下の3つで構成されます。

- `IpAddress`: ゲームサーバーの IP アドレス
- `Port`: 接続先ポート番号
- `EncryptionKey`: メッセージペイロードの暗号化キー

接続時にはアクセストークンとプレイヤーのプロフィール初期値を渡します。

## プロフィール

リレーサーバーは受け取ったメッセージを他プレイヤーに伝搬するだけでなく、プレイヤーごとにプロフィールデータを持つことができます。

新しいプレイヤーがゲームサーバーに接続した時に参加中の全ての他プレイヤーのプロフィールデータを受け取ることができます。
プレイヤーの基本情報を格納しておくことで、新規プレイヤーが接続してきた時の処理を簡略化することができます。

プロフィールを更新すると、他プレイヤーにその内容が送信されるためメッセージ送信の代わりにも使えなくはありませんが、
更新時にペイロード全体が送受信されるプロフィール更新で高頻度のメッセージングを行うのは通信効率的に最適ではありません。

プロフィールはバイナリペイロードとして任意のフォーマットでエンコードできます。
プレイヤーのキャラクター情報、装備、レベル、ゲーム内通貨などのスナップショットを格納するのに適しています。

## イベントハンドリング

`RelayRealtimeSession` には以下のイベントハンドラを設定できます。

| ハンドラ | 発火タイミング |
| -- | -- |
| `OnJoinPlayer` | 他プレイヤーがルームへ参加した時 |
| `OnLeavePlayer` | 他プレイヤーがルームから退出した時 |
| `OnRelayMessage` | 他プレイヤーからリレーメッセージを受信した時 |
| `OnUpdateProfile` | 他プレイヤーがプロフィールを更新した時 |
| `OnError` | プロトコルエラーが発生した時 |
| `OnGeneralError` | 通信エラーが発生した時 |
| `OnClose` | ゲームサーバーとの接続が切断された時 |

各イベントには `MessageMetadata` を含む拡張版（`OnRelayMessageWithMetadata` 等）も用意されており、メッセージのメタ情報を併せて取得できます。

## プッシュ通知

設定できる主なプッシュ通知と設定名は以下の通りです。

- `createNotification`: ルーム割り当て時に通知

`enableTransferMobileNotification` を有効にすると、オフライン端末へのモバイルプッシュ転送にも対応します。

GS2-Matchmaking で集まったメンバー全員にルーム割り当てを通知することで、対戦の準備完了をリアルタイムにアナウンスできます。

## マスターデータ運用

GS2-Realtime はマスターデータを必要としません。
ネームスペースの設定（サーバータイプ・サーバースペック・プッシュ通知設定）のみで運用できます。

## トランザクションアクション

GS2-Realtime ではトランザクションアクションを提供していません。

## 他マイクロサービスとの連携

GS2-Realtime は単独で利用するよりも、以下のマイクロサービスと組み合わせて使うのが一般的です。

| サービス | 用途 |
| -- | -- |
| GS2-Matchmaking | 対戦相手をマッチングし、成立後に `RoomWant` を呼び出す |
| GS2-Gateway | プッシュ通知の経路として `createNotification` を利用 |
| GS2-Account | プレイヤーのアクセストークンを発行 |

## 実装例

### ゲームサーバーへの接続情報を取得

ルーム名を指定して接続先情報を取得します。
`RoomWant` を経由してマッチメイク経由でルームが用意されている場合は、その `roomName` を指定します。



**Unity**
```csharp

    var item = await gs2.Realtime.Namespace(
        namespaceName: "namespace-0001"
    ).Room(
        roomName: "room-0001"
    ).ModelAsync();

    var ipAddress = item.IpAddress;
    var port = item.Port;
    var encryptionKey = item.EncryptionKey;
```
**Unreal Engine**
```cpp

    const auto Domain = Gs2->Realtime->Namespace(
        "namespace-0001" // namespaceName
    )->Room(
        "room-0001" // roomName
    );
    const auto Future = Domain->Model();
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError()) return false;
    const auto Result = Future->GetTask().Result();

    const auto IpAddress = Result->GetIpAddress();
    const auto Port = Result->GetPort();
    const auto EncryptionKey = Result->GetEncryptionKey();
```


### ゲームサーバーへ接続



**Unity**
```csharp

    using (
      var session = new RelayRealtimeSession(
         accessToken, // アクセストークン
         ipAddress, // ゲームサーバのIPアドレス
         port, // ゲームサーバのポート
         encryptionKey, // 暗号鍵
         ByteString.CopyFromUtf8("my profile") // プロフィールの初期値
      )
    )
    {
      // イベントハンドラを設定

      await session.ConnectAsync();

      // セッションが有効なスコープ
    }
```
**Unreal Engine**
```cpp

    // Unreal Engine 向け Realtime SDK は現在準備中です。
```


### 他プレイヤーの接続をハンドリング



**Unity**
```csharp

    session.OnJoinPlayer += player => {
        var connectionId = player.ConnectionId;
        var profile = player.Profile;
        // 新規参加者の初期表示などを行う
    };
```
**Unreal Engine**
```cpp

    // Unreal Engine 向け Realtime SDK は現在準備中です。
```


### 他プレイヤーの切断をハンドリング



**Unity**
```csharp

    session.OnLeavePlayer += player => {
        // 退出者の表示をクリーンアップする
    };
```
**Unreal Engine**
```cpp

    // Unreal Engine 向け Realtime SDK は現在準備中です。
```


### 他プレイヤーからのメッセージをハンドリング



**Unity**
```csharp

    session.OnRelayMessage += message => {
        var sourceConnectionId = message.ConnectionId;
        var payload = message.Data;
        // payload をアプリケーション層で復号・解釈
    };
```
**Unreal Engine**
```cpp

    // Unreal Engine 向け Realtime SDK は現在準備中です。
```


### 他プレイヤーのプロフィール更新をハンドリング



**Unity**
```csharp

    session.OnUpdateProfile += player => {
        // プロフィール変更を画面に反映
    };
```
**Unreal Engine**
```cpp

    // Unreal Engine 向け Realtime SDK は現在準備中です。
```


### ゲームサーバーからの切断をハンドリング



**Unity**
```csharp

    session.OnClose += () => {
        // 接続切断時のリトライ・遷移処理
    };
```
**Unreal Engine**
```cpp

    // Unreal Engine 向け Realtime SDK は現在準備中です。
```


### プロフィールを更新



**Unity**
```csharp

    await session.UpdateProfileAsync(
      ByteString.CopyFromUtf8("my profile2")
    );
```
**Unreal Engine**
```cpp

    // Unreal Engine 向け Realtime SDK は現在準備中です。
```


### ブロードキャストメッセージを送信

`targetConnectionIds` を省略すると、自身を除くルーム内の全プレイヤーへ配信されます。



**Unity**
```csharp

    await session.SendAsync(
      ByteString.CopyFrom(0x00, 0x01, 0x02)
    );
```
**Unreal Engine**
```cpp

    // Unreal Engine 向け Realtime SDK は現在準備中です。
```


### ユニキャストメッセージを送信

`targetConnectionIds` に対象プレイヤーの `ConnectionId` を指定します。
`ConnectionId` は `OnJoinPlayer` などで受け取れます。



**Unity**
```csharp

    await session.SendAsync(
      ByteString.CopyFrom(0x00, 0x01, 0x02),
      new uint[] { targetConnectionId1, targetConnectionId2 }
    );
```
**Unreal Engine**
```cpp

    // Unreal Engine 向け Realtime SDK は現在準備中です。
```


## 設計上の注意

### バイナリペイロードの設計

GS2-Realtime はバイナリデータをそのまま中継するだけで、内容を解釈しません。
そのため、以下の点はアプリケーション側で設計する必要があります。

- メッセージ種別を識別するためのヘッダ（先頭1バイトに opcode を入れるなど）
- シリアライズ形式（Protocol Buffers / FlatBuffers / MessagePack 等）
- 順序保証の必要性（必要な場合はアプリケーション層でシーケンス番号を付与）

### チート対策

リレーサーバーはペイロードの内容を解釈しないため、チート行為そのものを検知することはできません。
レーティングの計算などでは投票によって多数決で結果を決定します。

## 詳細なリファレンス

[GS2-Realtime API リファレンス](../../api_reference/realtime)



