# ユースケースサンプル: スコアが破られたプレイヤーにプッシュメッセージを送信する

> Send a push message to a player whose leaderboard score was beaten by another player.

このユースケースサンプルは、Triggers を使用して、リーダーボード内のスコアが破られたプレイヤーにプッシュメッセージを送信する方法を示します。サンプルでは、[Leaderboards サービス](/leaderboards.md) から `score-submitted` イベントを使用します。

> **Note:**
>
> **ノート**: Cloud Code モジュールでは [プッシュメッセージ](/cloud-code/modules/how-to-guides/push-messages.md) のみを使用できます。

## 前提条件##prerequisites

最初に、必要なアクセスロールでサービスアカウントを作成し、[UGS CLI](https://services.docs.unity.com/guides/ugs-cli/latest/general/get-started/install-the-cli/) を設定する必要があります。

### サービスアカウントを使用した認証##authenticate-using-a-service-account

Triggers サービスを呼び出す前に、サービスアカウントを使用して認証する必要があります。

1. [Unity Dashboard](https://cloud.unity.com) に移動します。
2. **Administration** (管理) > **Service Accounts** (サービスアカウント) を選択します。
3. **New** (新規) ボタンを選択し、サービスアカウントの名前と説明を入力します。
4. **Create** (作成) を選択します。

製品ロールを追加し、キーを作成します。

1. **Manage product roles** (製品ロールの管理) を選択します。
2. 以下のロールをサービスアカウントに追加します。
   * LiveOps ドロップダウンから、**Triggers Configuration Editor** (Triggers 設定編集者)、**Triggers Configuration Viewer** (Triggers 設定閲覧者)、**Leaderboards Admin** (Leaderboards 管理者) を選択します。
   * Admin (管理者) ドロップダウンから **Unity Environments Viewer** (Unity 環境閲覧者) を選択します。
3. **Save** (保存) を選択します。
4. **Add Key** (キーの追加) を選択します。
5. base64 エンコードを使用して **Key ID** (キー ID) と **Secret key** (秘密鍵) をエンコードします。形式は "key\_id:secret\_key" です。この値をメモしておきます。

詳細については、[Authentication](../../authentication) を参照してください。

### UGS CLI の設定##configure-the-ugs-cli

以下のステップに従って、UGS CLI の使用を準備します。

1. [UGS CLI をインストール](https://services.docs.unity.com/guides/ugs-cli/latest/general/get-started/install-the-cli/) します。

2. プロジェクト ID と環境を以下のように設定します。
   `ugs config set project-id <your-project-id>`
   `ugs config set environment-name <your-environment-name>`

3. 前に作成したサービスアカウントを使用して認証します。[認証の取得](https://services.docs.unity.com/guides/ugs-cli/latest/general/get-started/get-authenticated/) を参照してください。

## Leaderboards の設定##set-up-leaderboards

このサンプルに従うには、リーダーボードを作成する必要があります。

UGS CLI を使用して、以下の `leaderboard.lb` ファイルをデプロイできます。リーダーボードを昇順のソート順で定義し、ベストスコアを保持します。

`new-file` コマンドを実行して、リーダーボード設定をローカルに作成します。

```bash
ugs leaderboards new-file leaderboard
```

ファイル名はリーダーボード ID に対応します。以下の設定で `leaderboard.lb` ファイルを更新します。

```json
{
  "$schema": "https://ugs-config-schemas.unity3d.com/v1/leaderboards.schema.json",
  "SortOrder": "asc",
  "UpdateType": "keepBest",
  "Name": "leaderboard"
}
```

UGS CLI ツールを使用してファイルをデプロイします。

```bash
ugs deploy leaderboard.lb
```

リーダーボードを作成したので、そこにスコアを追加できます。

### 任意: リーダーボードへのスコアの追加##optional:-add-scores-to-the-leaderboard

以下の Cloud Code スクリプトを実行して、[Unity Dashboard](https://cloud.unity.com) からリーダーボードにスコアを追加できます。すべてのテスト実行でプレイヤー ID トークンを再生成して、新しいプレイヤーのスコアを生成してください。


**Frame:**
![](/api/media?file=/cloud-code/media/images/cloud-code-generate-button.png)

#### JavaScript##javascript

```javascript
const { LeaderboardsApi } = require("@unity-services/leaderboards-1.1");
const _ = require("lodash-4.17");

module.exports = async ({ params, context, logger }) => {
  const leaderboardsApi = new LeaderboardsApi({ accessToken: context.accessToken });
  const leaderboardID = "leaderboard";

  var randomScore = _.random(1, 100);
  try {
    await leaderboardsApi.addLeaderboardPlayerScore(context.projectId, leaderboardID, context.playerId, { score: randomScore });
  } catch (err) {

    logger.error("Failed to add score to the leaderboard", { "error.message": err.message });
  }
};
```

## `score-submitted` イベントを調べる##examine-the-score-submitted-event

Leaderboards サービスは、新しいスコアがリーダーボードに送信されたときに `score-submitted` イベントを発行します。イベントペイロードは以下のようになります。

```json
{
  "leaderboardId": "leaderboard",
  "updatedTime": "2019-08-24T14:15:22Z",
  "playerId": "5drhidte8XgD4658j2eHtSljIAzd",
  "playerName": "Jane Doe",
  "rank": 42,
  "score": 120.3,
  "tier": "gold"
}
```

イベントは、イベントペイロードをパラメーターとして Cloud Code に渡します。

詳細については、[Leaderboards: スコア送信](/triggers/manage-events/supported-ugs-events.md#score-submitted) を参照してください。

## Cloud Code の設定##set-up-cloud-code

スコアが破られたプレイヤーにプッシュメッセージを送信するモジュールエンドポイントを定義します。

以下のようなコンテンツで `SendPushNotification` モジュール関数を作成します。

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

namespace LeaderboardsNotification;

public class LeaderboardsNotification
{
    private readonly ILogger<LeaderboardsNotification> _logger;

    public LeaderboardsNotification(ILogger<LeaderboardsNotification> logger)
    {
        _logger = logger;
    }

    [CloudCodeFunction("SendPlayerMessage")]
    public async Task SendPlayerMessage(IExecutionContext context, IGameApiClient gameApiClient, PushClient pushClient, string playerId, string playerName,
        string leaderboardId, double score)
    {
        try
        {
            var closestPlayers = await gameApiClient.Leaderboards.GetLeaderboardScoresPlayerRangeAsync(context,
                context.ServiceToken, new Guid(context.ProjectId), leaderboardId, playerId, 1);

            if (closestPlayers.Data.Results.Count != 0)
            {
                var player = closestPlayers.Data.Results[^1];
                string message =
                    $"The player {playerName} has just beaten your score of {player.Score} on the {leaderboardId} leaderboard by {score-player.Score} points!";

                await pushClient.SendPlayerMessageAsync(context, message, "Information", player.PlayerId);
            }
        }
        catch (ApiException e)
        {
            _logger.LogError("Failed to send push notification to player {playerId}. Error: {Error}", playerId, e.Message);
            throw new Exception($"Failed to send push notification to player {playerId}. Error: {e.Message}");
        }
    }
}


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

モジュールをデプロイします。

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

> **Note:**
>
> **ノート:** UGS CLI を使用してモジュールをデプロイする場合は、`Cloud Code Editor` の追加のサービスアカウントロールを忘れずに追加してください。

## トリガーの設定##configure-a-trigger

Cloud Code リソースを Leaderboards `score-submitted` イベントに接続するには、トリガーを作成します。トリガーは、イベントが発生したとき、例えば新しいスコアが送信されるたびに、Cloud Code モジュールを実行します。

`new-file` コマンドを実行して、トリガー設定をローカルに作成します。

```bash
ugs triggers new-file triggers-config
```

以下の設定で `triggers-config.tr` ファイルを更新します。

```json
{
  "$schema": "https://ugs-config-schemas.unity3d.com/v1/triggers.schema.json",
  "Configs": [
    {
      "Name": "score-beaten-message",
      "EventType": "com.unity.services.leaderboards.score-submitted.v1",
      "ActionUrn": "urn:ugs:cloud-code:LeaderboardsNotification/SendPlayerMessage",
      "ActionType": "cloud-code"
    }
  ]
}
```

UGS CLI ツールを使用して設定をデプロイします。

```bash
ugs deploy triggers-config.tr
```

成功レスポンスは以下のようになります。

```text
Deployed:
    triggers-config.tr
```

サンプルトリガーは、プレイヤーがサインアップしたときに Cloud Code モジュール関数を実行します。

## 結果の検証##validate-the-result

結果を検証するには、プッシュメッセージをサブスクライブする Unity プロジェクトを設定し、[前に作成した Cloud Code スクリプト](#optional:-add-scores-to-the-leaderboard) を使用してリーダーボードに新しいスコアを送信します。

### 前提条件##prerequisites

プッシュメッセージをサブスクライブするには、Cloud Code SDK をインストールし、[Unity Gaming Services プロジェクト](/cloud/projects.md) を Unity エディターにリンクする必要があります。

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

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

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 のインストール##sdkinstallation

Unity エディターの最新の Cloud Code パッケージをインストールするには、以下を行います。

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

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

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

### `Monobehaviour` スクリプトの作成##create-a-monobehaviour-script

プレイヤーレベルのメッセージをサブスクライブするには、`Monobehaviour` スクリプトを設定します。詳細については、[プッシュメッセージの送信](/cloud-code/modules/how-to-guides/push-messages.md) を参照してください。

`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();
        }

        // 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);
        }
	}
}
```

`Monobehaviour` スクリプトを初めて実行したときに、プレイヤー ID がログに記録されます。指定した ID のスコアを送信するように [Cloud Code スクリプト](#optional:-add-scores-to-the-leaderboard) を変更して、プレイヤーをリーダーボードに追加できます。

もう一度スクリプトを実行して、リーダーボードのスコアを生成します。

Unity エディターに、プレイヤースコアが破られたときに送信されたプッシュメッセージが表示されます。

```yaml
Got player subscription Message: {
  "data_base64": <BASE64-ENCODED-DATA>,
  "time": "2023-09-19T10:26:40.436878688Z",
  "message": "The player AdjacentMowingToga#7 has just beaten your score of 120.3 on the my-leaderboard leaderboard by 51.3 points!",
  "specversion": "1.0",
  "id": <ID>,
  "source": "https://cloud-code.service.api.unity.com",
  "type": "com.unity.services.cloud-code.push.v1",
  "projectid": <PROJECT-ID>,
  "environmentid": <ENVIRONMENT-ID>,
  "correlationid": <CORRELATION-ID>,
  "messagetype": "Information"
}
```
