# 사용 사례 샘플: 순위가 떨어진 플레이어에게 푸시 메시지 전송

> 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 Configuration Viewer**, **Leaderboards Admin**을 선택합니다.
   * Admin 드롭다운에서 **Unity Environments Viewer**를 선택합니다.
3. **Save**를 선택합니다.
4. **Add Key**를 선택합니다.
5. base64 인코딩을 사용하여 **Key ID**와 **Secret key**를 인코딩합니다. 포맷은 ‘key\_id:secret\_key’입니다. 이 값을 기록해 둡니다.

자세한 내용은 [인증](../../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 에디터와 연결합니다. [Unity Dashboard](https://cloud.unity.com)에서 UGS 프로젝트 ID를 확인할 수 있습니다.

1. Unity 에디터에서 **Edit** > **Project Settings** > **Services**를 선택합니다.

2. 프로젝트를 연결합니다.
   프로젝트에 Unity 프로젝트 ID가 없는 경우 다음 단계를 진행합니다.

   1. **Create a Unity Project ID** > **Organizations**를 선택한 다음 드롭다운에서 조직을 선택합니다.
   2. **Create project ID**를 선택합니다.

   Unity 프로젝트 ID가 있는 경우 다음 단계를 진행합니다.

   1. **Use an existing Unity project ID**를 선택합니다.
   2. 드롭다운에서 조직과 프로젝트를 선택합니다.
   3. **Link project ID**를 선택합니다.

Unity 프로젝트 ID가 표시되고 이제 Unity 서비스에 프로젝트가 연결됩니다. `UnityEditor.CloudProjectSettings.projectId`를 사용하여 Unity 에디터 스크립트에서 프로젝트 ID에 액세스할 수도 있습니다.

#### SDK 설치##sdkinstallation

다음 단계를 따라 Unity 에디터용 최신 Cloud Code 패키지를 설치합니다.

1. Unity 에디터에서 **Window** > **Package Manager**를 엽니다.
2. 패키지 관리자에서 **Unity Registry** 목록 뷰를 선택합니다.
3. `com.unity.services.cloudcode`를 검색하거나 목록에서 Cloud Code 패키지를 찾습니다.
4. 패키지를 선택한 후 **Install**을 선택합니다.

> **Note:**
>
> [Unity - 매뉴얼: Package Manager 창](https://docs.unity3d.com/Manual/upm-ui.html)을 확인하여 Unity 패키지 관리자 인터페이스를 익혀 두십시오.

> **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가 기록됩니다. [Cloud Code 스크립트](#optional:-add-scores-to-the-leaderboard)를 수정하여 지정된 ID의 점수를 제출하면 플레이어를 리더보드에 추가할 수 있습니다.

리더보드의 점수를 생성하려면 스크립트를 다시 실행합니다.

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"
}
```
