# プッシュメッセージの送信

> Push messages to clients over a WebSocket connection from Cloud Code modules.

Cloud Code C# モジュールでは、WebSocket を介してメッセージをクライアントにプッシュできます。このページでは、この機能の概要と、Cloud Code モジュールおよび Cloud Code SDK で使用する方法について説明します。

> **Note:**
>
> **ノート**: プッシュメッセージと [プッシュ通知](/push-notifications.md) は、ゲーム内で異なる目的を果たします。プッシュメッセージはゲームプレイをアクティブに行っているプレイヤーをターゲットとし、ゲームが非アクティブであるかバックグラウンドで動作している場合にはプッシュ通知がデバイスに届きます。

プッシュメッセージを送信するには、モジュールエンドポイントを呼び出す必要があります。Unity エディターからプッシュメッセージをサブスクライブできます。

## ユースケースと利点##use-cases-and-benefits

プッシュメッセージは、以下のようなさまざまな目的に使用できます。

| 用途                                                                | 例                                                                                                                               | 利点              |
| :---------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------ | :-------------- |
| サーバーからクライアントにリアルタイムでメッセージをプッシュし、ゲームのインタラクティビティを強化します。             | ゲームイベント、更新、非同期マルチプレイヤーゲーム (例えば、競争型カードゲームなど) についてプレイヤーに通知できます。                                                                   | リアルタイムインタラクション  |
| 更新と通知をクライアントに直接プッシュすることにより、ゲーム内の最新のイベント、変更、またはアクションでユーザーを最新に保ちます。 | 新しいデータが使用可能になるとすぐにユーザーに通知できるため、手動でリフレッシュしたり、更新を確認したりする必要がありません。これは、リアルタイムストラテジーゲームなど、頻繁な更新が必要なゲームで特に役立つ可能性があります。                | ユーザー体験          |
| WebSocket を使用して、従来のポーリング手法よりも効率よくメッセージをプッシュします。                   | クライアントは、新しいデータについて継続的にサーバーに尋ねるかわりに、新しいデータが使用可能になったときに、サーバーがそれを送信するのを待つことができます。これにより、不必要なネットワークトラフィックが削減され、待ち時間の短縮につながる可能性があります。 | 効率的なネットワーク使用状況  |
| プッシュモデルのスケーラビリティを使用して、ユーザー数の多いゲームをサポートします。                        | Cloud Code でプッシュメッセージを使用して、接続されているすべてのクライアントに更新を一度に送信し、プレイヤー数の多いマルチプレイヤーゲームの運用コストとリクエストの量を削減できます。                               | スケーラビリティとコスト    |
| イベント主導モデルでさまざまなタイプのメッセージへのゲームのレスポンスをカスタマイズします。                    | 受信したメッセージの MessageType プロパティに基づいて異なるゲームアクションをトリガーできます。                                                                          | カスタマイズ可能性       |
| Unity エコシステムの一部として、Cloud Code の使用は他の Unity サービスとシームレスに行われます。      | Unity の Authentication サービスでプレイヤー認証を処理し、Unity ゲームエンジン内でメッセージを処理できます。                                                            | シームレスなインテグレーション |

## モジュールの作成##create-a-module

以下のコード例は、2 つのメソッドを含むモジュールの基本構造を示します。

* `SendPlayerMessage`: 特定の接続済みプレイヤーにメッセージを送信します。
* `SendProjectMessage`: プロジェクト内のすべての接続済みプレイヤーにメッセージをブロードキャストします。

> **Warning:**
>
> **重要**: `SendProjectMessage` メソッドは、プロジェクト内のすべての接続済みプレイヤーにメッセージを送信します。これは、プレイヤーに対するスパムメッセージのような乱用を招く可能性があります。これを防ぐために、[アクセス制御](./access-control.md) ポリシーを作成して、プレイヤーによるエンドポイントへのアクセスを制限できます。

> **Note:**
>
> **ノート**: メッセージをプロジェクト全体にブロードキャストするには [Triggers](/triggers.md) を使用できます。[ユースケースサンプル:プレイヤーに新年の挨拶をする](/triggers/tutorials/use-cases/happy-new-year.md)。

`Unity.Services.CloudCode.Apis` パッケージは、`PushClient` インスタンスを提供します。これは、プッシュメッセージの送信に使用するインターフェースです。

```csharp
using Microsoft.Extensions.DependencyInjection;
using Unity.Services.CloudCode.Core;
using Unity.Services.CloudCode.Apis;

namespace PushExample
{
    public class PushExample
    {
        [CloudCodeFunction("SendPlayerMessage")]
        public async Task<string> SendPlayerMessage(IExecutionContext context, PushClient pushClient, string message, string messageType, string playerId)
        {
            var response = await pushClient.SendPlayerMessageAsync(context, message, messageType, playerId);
            return "Player message sent";
        }

        // Recommended to use access control to limit access to this endpoint
        [CloudCodeFunction("SendProjectMessage")]
        public async Task<string> SendProjectMessage(IExecutionContext context, PushClient pushClient, string message, string messageType)
        {
            var response = await pushClient.SendProjectMessageAsync(context, message, messageType);
            return "Project message sent";
        }
    }

    public class ModuleConfig : ICloudCodeSetup
    {
        public void Setup(ICloudCodeConfig config)
        {
            config.Dependencies.AddSingleton(PushClient.Create());
        }
    }
}
```

モジュールのデプロイ方法を学習するには、[Hello World のデプロイ](../getting-started) ページを参照してください。

## Unity エディターの設定##set-up-the-unity-editor

Cloud Code SDK は、メッセージをサブスクライブするためのインターフェースを提供します。特定のプレイヤーまたはプロジェクト全体のメッセージをサブスクライブできます。

Unity エディターで Cloud Code を使用するには、最初に Cloud Code SDK をインストールし、[Unity Gaming Services プロジェクト](/cloud/projects.md) を Unity エディターにリンクする必要があります。

### プロジェクトのリンク##link-project

[Unity Gaming Services プロジェクト](/cloud/projects.md) を Unity エディターにリンクします。UGS プロジェクト ID は Unity Dashboard にあります。

1. Unity エディターで、**Edit** (編集) > **Project Settings** (プロジェクト設定) > **Services** (サービス) の順に選択します。

2. プロジェクトをリンクします。
   プロジェクトに Unity プロジェクト ID がない場合:

   1. **Create a Unity Project ID** (Unity プロジェクト ID の作成) > **Organizations** (組織) の順に選択し、ドロップダウンから組織を選択します。
   2. **Create project ID** (プロジェクト ID を作成) を選択します。

   既存の Unity プロジェクト ID がある場合:

   1. **Use an existing Unity project ID** (既存の Unity プロジェクト ID を使用) を選択します。
   2. ドロップダウンから組織とプロジェクトを選択します。
   3. **Link project ID** (プロジェクト ID をリンク) を選択します。

これにより、Unity プロジェクト ID が表示され、プロジェクトが Unity サービスにリンクされます。また、`UnityEditor.CloudProjectSettings.projectId` パラメーターを使用して Unity エディタースクリプトのプロジェクト ID にアクセスすることもできます。

### SDK のインストール##sdk-installation

Unity エディターの最新の Cloud Code パッケージをインストールします。

1. Unity エディターで、**Window** (ウィンドウ) > **Package Manager** (パッケージマネージャー) を開きます。
2. Package Manager で、**Unity Registry** (Unity レジストリ) のリストビューを選択します。
3. `com.unity.services.cloudcode` を検索するか、リストから Cloud Code パッケージを探します。
4. このパッケージを選択し、**Install** (インストール) をクリックします。

> **Note:**
>
> **ノート**: Cloud Code SDK バージョン 2.4.0 以上でメッセージをサブスクライブできます。

> **Note:**
>
> **ノート**: Unity Package Manager インターフェースについて理解するには、[Package Manager ウィンドウ](https://docs.unity3d.com/Manual/upm-ui.html) のドキュメントを参照してください。

### SDK の設定##sdk-setup

Cloud Code SDK の使用を準備します。

1. Cloud Code サービスダッシュボードページを介してサービスが有効になっていることを確認します。
2. Cloud Code と Authentication SDK の両方をインストールしたことを確認します。
3. **Edit** (編集) > **Project Settings** (プロジェクト設定) > **Services** (サービス) を選択して、Unity エディター内からクラウドプロジェクトにサインインします。
4. Unity エディターで新しい C# Monobehaviour スクリプトを作成します。Unity マニュアルの [スクリプトの作成と使用](https://docs.unity3d.com/Manual/CreatingAndUsingScripts.html) を参照してください。
5. スクリプトで、await `UnityServices.InitializeAsync()` を使用して Core SDK を初期化します。
6. スクリプトで、Authentication SDK を初期化します。

> **Note:**
>
> **ノート**: プレイヤーが Cloud Code サービスにアクセスするには有効なプレイヤー ID とアクセストークンが必要です。いずれかの Cloud Code API を使用する前にプレイヤーを Authentication SDK で認証する必要があります。これを匿名認証用の以下のコードスニペットで行うか、詳細および他のサインイン方法について [Authentication](/authentication.md) のドキュメントを確認できます。

```cs
await AuthenticationService.Instance.SignInAnonymouslyAsync();
```

## メッセージのサブスクライブ##subscribe-to-messages

特定のプレイヤーまたはプロジェクト全体のメッセージをサブスクライブできます。以下のコードスニペットを、Unity プロジェクトの `MonoBehaviour` スクリプトのガイドとして使用できます。

スクリプトは匿名プレイヤーとして認証され、プレイヤー固有とプロジェクト固有の両方のメッセージをサブスクライブし、さまざまなタイプのイベントを処理します。

```csharp
using System;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Unity.Services.Authentication;
using Unity.Services.CloudCode;
using Unity.Services.CloudCode.Subscriptions;
using Unity.Services.Core;
using UnityEngine;
namespace CloudCode
{
	public class CloudCodePushExample : MonoBehaviour
	{
    	async void Start()
        {
            await UnityServices.InitializeAsync();
            await AuthenticationService.Instance.SignInAnonymouslyAsync();
            Debug.Log(AuthenticationService.Instance.PlayerId);
            await SubscribeToPlayerMessages();
            await SubscribeToProjectMessages();
        }
        // This method creates a subscription to player messages and logs out the messages received,
        // the state changes of the connection, when the player is kicked and when an error occurs.
        Task SubscribeToPlayerMessages()
        {
            // Register callbacks, which are triggered when a player message is received
            var callbacks = new SubscriptionEventCallbacks();
            callbacks.MessageReceived += @event =>
            {
                Debug.Log(DateTime.Now.ToString("yyyy-MM-dd'T'HH:mm:ss.fffK"));
                Debug.Log($"Got player subscription Message: {JsonConvert.SerializeObject(@event, Formatting.Indented)}");
            };
            callbacks.ConnectionStateChanged += @event =>
            {
                Debug.Log($"Got player subscription ConnectionStateChanged: {JsonConvert.SerializeObject(@event, Formatting.Indented)}");
            };
            callbacks.Kicked += () =>
            {
                Debug.Log($"Got player subscription Kicked");
            };
            callbacks.Error += @event =>
            {
                Debug.Log($"Got player subscription Error: {JsonConvert.SerializeObject(@event, Formatting.Indented)}");
            };
            return CloudCodeService.Instance.SubscribeToPlayerMessagesAsync(callbacks);
        }
        // This method creates a subscription to project messages and logs out the messages received,
        // the state changes of the connection, when the player is kicked and when an error occurs.
        Task SubscribeToProjectMessages()
        {
            var callbacks = new SubscriptionEventCallbacks();
            callbacks.MessageReceived += @event =>
            {
                Debug.Log(DateTime.Now.ToString("yyyy-MM-dd'T'HH:mm:ss.fffK"));
                Debug.Log($"Got project subscription Message: {JsonConvert.SerializeObject(@event, Formatting.Indented)}");
            };
            callbacks.ConnectionStateChanged += @event =>
            {
                Debug.Log($"Got project subscription ConnectionStateChanged: {JsonConvert.SerializeObject(@event, Formatting.Indented)}");
            };
            callbacks.Kicked += () =>
            {
                Debug.Log($"Got project subscription Kicked");
            };
            callbacks.Error += @event =>
            {
                Debug.Log($"Got project subscription Error: {JsonConvert.SerializeObject(@event, Formatting.Indented)}");
            };
            return CloudCodeService.Instance.SubscribeToProjectMessagesAsync(callbacks);
        }
	}
}
```

## プレイヤーへのメッセージの送信##send-messages-to-players

プレイヤーにメッセージを送信するには、モジュールから `SendPlayerMessage` または `SendProjectMessage` 関数を呼び出します。

モジュールを実行する方法については、[モジュールの実行](./run-modules.md) を参照してください。

### Unity Runtime からの実行##run-from-unity-runtime

`CloudCodeService` インスタンスの `CallModuleEndpointAsync` メソッドを介して他のプレイヤーにメッセージを送信できます。モジュール名と関数名を最初の 2 つの引数として使用し、ディクショナリと必要なパラメーターを 3 番目の引数として使用する必要があります。

例えば、プレイヤーにメッセージを送信するには、以下を呼び出します。

```csharp
var sendPlayerMessageResult = await CloudCodeService.Instance.CallModuleEndpointAsync<string>("PushExample", "SendPlayerMessage",
	new Dictionary<string, object> {{"message", "hello with a player message from PushExample!"}, {"messageType", "testType"}, {"playerId", "<other-unity-player-ID>"}});
```

> **Note:**
>
> **ノート**: プロジェクトメッセージをゲーム内の他のすべてのプレイヤーに送信する `SendProjectMessage` モジュール関数の呼び出しをプレイヤーに対して拒否する、[アクセス制御](./access-control.md) ポリシーを作成できます。

## イベント##events

プレイヤー固有とプロジェクト固有の両方のサブスクリプションには、4 つのイベントハンドラーがあります。

* `MessageReceived`: プレイヤーが新しいメッセージを受信したときにトリガーします。
* `ConnectionStateChanged`: 接続の状態が変わったときにトリガーします。
* `Kicked`: サーバーがプレイヤーのメッセージのサブスクライブを強制的に解除したときにトリガーします。これにより WebSocket 接続はクローズされず、ゲームクライアントがメッセージを再びサブスクライブすることも阻止されません。
* `Error`: 接続の処理時またはプレイヤーがメッセージを受信したときにトリガーします。

## メッセージエンベロープ##message-envelope

`IMessageReceivedEvent` は、プレイヤーがプッシュサービスから受信するメッセージを表すインターフェースです。イベントは、Cloud Code が WebSocket 接続を介してメッセージを送信したときにトリガーします。

`IMessageReceivedEvent` インターフェースのペイロードについては、以下の表を参照してください。

| プロパティ           | 説明                                                                                                  | 例                                          |
| --------------- | --------------------------------------------------------------------------------------------------- | ------------------------------------------ |
| `SpecVersion`   | 受信したメッセージのエンベロープの仕様バージョン。このプロパティを使用して、クライアントがメッセージを正しく処理できることを確認します。                                | 1.0                                        |
| `Id`            | メッセージの一意の識別子。このプロパティを使用して、メッセージを追跡またはログに記録します。                                                      | `4f88f657-27da-4b1d-a013-9033dbc7b48b`     |
| `Source`        | メッセージのエンベロープのソース。これは、メッセージが発生した場所を示し、メッセージのデバッグまたはルーティングに使用できます。ソースは常に Cloud Code のドメインです。          | `https://cloud-code.service.api.unity.com` |
| `Type`          | メッセージのエンベロープタイプ。このプロパティは、メッセージに含まれるデータのタイプを示し、クライアントがその処理方法を決定するのに役立ちます。値は常に Cloud Code メッセージタイプです。 | `com.unity.services.cloud-code.push.v1`    |
| `Time`          | メッセージ作成の日付と時間。このプロパティを使用して、メッセージをログに記録したり、待ち時間を計算したりできます。                                           | `2023-09-19T10:26:40.436878688Z`           |
| `ProjectId`     | メッセージが関連付けられているプロジェクトの ID。                                                                          | `b6670776-9fd3-4d66-8bf4-63fb1112dc95`     |
| `EnvironmentId` | メッセージが対象としている環境の ID。このプロパティを使用して、開発、ステージング、運用などのさまざまな環境を区別できます。                                     | `a4bc2571-d1e7-4507-9cc9-80b687d48d8f`     |
| `CorrelationId` | 関連メッセージの順序を追跡するために使用できる識別子。例えば、複数のメッセージが会話またはワークフローを形成する場合、それらは相関 ID を共有します。                        | `afbd7c6e-e999-4ca2-86fc-3c908ba83bf2`     |
| `Message`       | Cloud Code からプレイヤーに送信された実際のメッセージコンテンツ。                                                              | "hello world!"                             |
| `MessageType`   | プレイヤーが受信するメッセージのタイプ。これは `Type` と同様ですが、エンベロープではなくメッセージのコンテンツに固有です。                                   | "Information"                              |
