# 开始使用

> Follow this workflow to set up Triggers and automate rewarding top players from Leaderboards.

本节介绍开始使用 Triggers 所需的所有步骤。

以下示例演示了如何使用 Triggers 在 [Cloud Save](/cloud-save.md) 中根据 Scheduler 发出的一次性计划事件向 [Leaderboards](/leaderboards.md) 排行榜前五名玩家授予相应的赛季奖杯。

## 视频演示##video-walkthrough

观看下面的视频，了解在 Unity Dashboard（Unity 后台）中创建触发器的具体步骤。


[Video content](https://youtu.be/eTnxB3OczOY)

## 典型工作流程##typical-workflow

要开始使用 Triggers，请执行以下步骤：

1. [创建一个要在事件发生时运行的 Cloud Code 脚本或模块：](#set-up-cloud-code)定义触发事件时要执行的游戏逻辑。
2. [计划一个事件以更改资源的状态：](#schedule-an-event)定义触发事件的时间。
3. [配置一个触发器以在事件发生时执行 Cloud Code 模块终端：](#configure-a-trigger)定义触发事件时要执行的 Cloud Code 脚本或模块。
4. [验证结果：](#validate-the-result)检查是否已执行 Cloud Code 脚本或模块。

> **Note:**
>
> **注意**：还可以将 Triggers 用于其他服务发出的事件。如需了解更多信息，请参阅[事件](./manage-events/events.md)一节。

## 先决条件##prerequisites

以下步骤假定您已经[在 Unity Dashboard 中创建了 Unity Gaming Services（Unity 游戏服务）项目](/cloud/projects/create-project.md)。

必须首先创建具有所需访问角色的服务帐户，并配置 [UGS CLI](https://services.docs.unity.com/guides/ugs-cli/latest/general/get-started/install-the-cli/)。

### 使用服务帐户进行身份验证##authenticate-using-a-service-account

在调用 Scheduling 和 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 配置查看者）**、**Scheduler Configuration Editor（Scheduler 配置编辑者）**、**Scheduler Configuration Viewer（Scheduler 配置查看者）** 和 **Leaderboards Admin（Leaderboards 管理员）**。
   * 从 Admin（管理）下拉选单中，选择 **Unity Environments Viewer（Unity 环境查看者）**。
3. 选择 **Save（保存）**。
4. 选择 **Add Key（添加密钥）**。
5. 使用 base64 编码方式对 **Key ID（密钥 ID）** 和 **Secret key（密钥）** 进行编码。格式为“key\_id:secret\_key”。请记下此值。

如需了解更多信息，请参阅[身份验证](/triggers/authentication.md)。

### 配置 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. 按如下方式配置 Project 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 令牌，以便为新玩家生成分数。

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

## 设置 Cloud Code##set-up-cloud-code

要使用 Triggers，您应该定义一个 Cloud Code 模块或 Cloud Code 脚本。触发器触发时将执行这个模块或脚本。以下示例会将 [Leaderboards](/leaderboards.md) 和 [Cloud Save](/cloud-save.md) 与 Cloud Code 集成在一起，向排行榜前五名的玩家授予赛季奖杯。

### Cloud Code C# 模块##cloud-code-c-module

定义一个 `SchedulerHelloWorld` 模块，其中包含一个接受字符串参数 `key` 和 `value` 的函数。

模块终端 `RewardPlayers` 从排行榜中获取前五名玩家，并使用指定的键和值为每个玩家设置 Cloud Save 数据。

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

namespace SchedulerHelloWorld;

public class SchedulerHelloWorld
{
    private const string LeaderboardId = "leaderboard";
    private readonly ILogger<SchedulerHelloWorld> _logger;
    public SchedulerHelloWorld(ILogger<SchedulerHelloWorld> logger)
    {
        _logger = logger;
    }

    [CloudCodeFunction("RewardPlayers")]
    public async Task RewardPlayers(IExecutionContext ctx, IGameApiClient gameApiClient, string key, string value)
    {
        var top5Players = await GetTop5(ctx, gameApiClient);
        foreach (var score in top5Players)
        {
            try
            {
                var response = await gameApiClient.CloudSaveData.SetItemAsync(ctx, ctx.ServiceToken, ctx.ProjectId, score.PlayerId, new SetItemBody(key, value));
                _logger.LogInformation("Data saved successfully");
            }
            catch (ApiException e)
            {
                _logger.LogError( "Failed to record data for playerId {playerId}. Error: {Error}", score.PlayerId, e.Message);
                throw new Exception($"Failed to record data for playerId {score.PlayerId}. Error: {e.Message}");
            }
        }
    }

    [CloudCodeFunction("GetTopPlayers")]
    public async Task<List<LeaderboardEntry>> GetTop5(IExecutionContext ctx, IGameApiClient gameApiClient)
    {
        try
        {
            var results = await gameApiClient.Leaderboards.GetLeaderboardScoresAsync(ctx, ctx.ServiceToken, new Guid(ctx.ProjectId),
                LeaderboardId, null, 5);
            return results.Data.Results;

        }
        catch (ApiException e)
        {
            _logger.LogError(e, "Failed to get top players for leaderboard: {LeaderboardId}. Error: {Error}", LeaderboardId, e.Message);
            throw new Exception($"Failed to get top players for leaderboard: {LeaderboardId}. Error: {e.Message}");
        }
    }

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

}
```

部署该模块。

请参阅[部署 Hello World](/cloud-code/modules/getting-started.md#deploy-the-module) 以了解如何部署模块。

> **Note:**
>
> **注意：** 如果您使用 UGS CLI 来部署模块，请不要忘记添加额外的服务帐户角色 `Cloud Code Editor`。

### Cloud Code JavaScript 脚本##cloud-code-javascript-script

您可以通过创建 Cloud Code 脚本来实现相同的结果。

创建一个包含必需字符串参数 `key` 和 `value` 的 `SchedulerHelloWorld` 脚本：

#### JavaScript##javascript

```javascript
const { DataApi } = require("@unity-services/cloud-save-1.4");
const { LeaderboardsApi } = require("@unity-services/leaderboards-1.1");


module.exports = async ({ params, context, logger }) => {
  // Get top 5 players from the Leaderboard
  const leaderboardId = "my-leaderboard";
  const leaderboardsApi = new LeaderboardsApi(context);
  const cloudSaveApi = new DataApi(context);

  let result;

  try {
    result = await leaderboardsApi.getLeaderboardScores(context.projectId, leaderboardId, 0, 5);
  } catch (err) {
    logger.error("Failed to retrieve players from the leaderboard", { "error.message": err.message });
    throw err;
  }

  // Set Cloud Save data for every player
  const promises = result.data.results.map(async (score) => {
    try {

      await cloudSaveApi.setItem(context.projectId, score.playerId, {
        key: params.key,
        value: params.value,
      });

    } catch (err) {
      logger.error("Failed to update Cloud Save data", { "error.message": err.message }, { "affectedPlayerId": score.playerId });
      return;
    }
  });

  await Promise.all(promises);
};
```

发布该脚本。

请参阅[部署 Hello World](/cloud-code/scripts/getting-started.md#deploying-hello-world) 以了解如何部署脚本。

> **Note:**
>
> **注意：** 如果您使用 UGS CLI 来部署脚本，请不要忘记添加额外的服务帐户角色 `Cloud Code Script Publisher` 和 `Cloud Code Editor`。

## 计划事件##schedule-an-event

定义 Cloud Code 脚本或模块后，您可以创建一个计划来确定向前五名玩家授予奖杯的时间。

以下示例定义了一个向玩家授予赛季奖杯的一次性计划。

运行 `new-file` 命令在本地创建计划配置：

```bash
ugs scheduler new-file schedule-config
```

使用以下配置来更新 `schedule-config.sched` 文件：

```json
{
  "$schema": "https://ugs-config-schemas.unity3d.com/v1/schedules.schema.json",
  "Configs": {
    "grant-trophy": {
      "EventName": "trophy-for-top-5",
      "Type": "one-time",
      "Schedule": "2024-08-28T00:00:00Z",
      "PayloadVersion": 1,
      "Payload": "{\"key\": \"seasonal-trophy\", \"value\": \"2024-08-28\"}"
    }
  }
}
```

事件的 `payload` 携带传递给 Cloud Code 脚本或模块的 Cloud Code 参数。修改 `schedule` 字段以更改触发事件的日期和时间。

使用 UGS CLI 工具部署此配置：

```bash
ugs deploy schedule-config.sched
```

您应该会看到类似于以下内容的响应：

```text
Deployed:
    schedule-config.sched
```

现在，您有了一个在特定时间触发事件的计划。但是，这些事件尚未关联到您的 Cloud Code 脚本或模块。

## 配置触发器##configure-a-trigger

要将 Cloud Code 资源关联到计划，请创建触发器。触发器会在触发事件时（例如，触发计划时）执行 Cloud Code 模块或脚本。

运行 `new-file` 命令在本地创建触发器配置：

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

如果您创建了 Cloud Code 模块，请使用以下配置来更新 `triggers-config.tr` 文件：

```json
{
  "$schema": "https://ugs-config-schemas.unity3d.com/v1/triggers.schema.json",
  "Configs": [
    {
      "Name": "trophy-reward",
      "EventType": "com.unity.services.scheduler.trophy-for-top-5.v1",
      "ActionUrn": "urn:ugs:cloud-code:SchedulerHelloWorld/RewardPlayers",
      "ActionType": "cloud-code"
    }
  ]
}
```

如果您创建了 Cloud Code 脚本，请使用以下配置来更新 `triggers-config.tr` 文件：

```json
{
  "$schema": "https://ugs-config-schemas.unity3d.com/v1/triggers.schema.json",
  "Configs": [
    {
      "Name": "trophy-reward",
      "EventType": "com.unity.services.scheduler.trophy-for-top-5.v1",
      "ActionUrn": "urn:ugs:cloud-code:SchedulerHelloWorld",
      "ActionType": "cloud-code"
    }
  ]
}
```

使用 UGS CLI 工具部署此配置：

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

您应该会看到类似于以下内容的响应：

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

现在，您有了一个触发器会在触发事件时执行 Cloud Code 脚本或模块。

## 验证结果##validate-the-result

要验证结果，您可以在触发事件之前和之后检查排名靠前的玩家。

1. 导航到 [Unity Dashboard](https://cloud.unity.com)。
2. 选择 **Products（产品）**> **Leaderboards**。
3. 选择 **Overview（概览）** 部分。
4. 选择 `leaderboard` 排行榜。
5. 选择 **Entries（条目）** 选项卡。
6. 记下排名靠前的玩家 ID 之一。

要验证玩家数据是否已更新，可以检查玩家的 Cloud Save 数据：

1. 在 [Unity Dashboard](https://cloud.unity.com) 中，选择 **Products（产品）**> **Player Management（玩家管理）**。
2. 在搜索字段中，输入您先前记下的玩家 ID，然后选择 **Find Player（查找玩家）**。
3. 导航到 **Cloud Save** > **Data（数据）** 部分。
4. 您应该会发现值为 `2023-08-28` 的 `seasonal-trophy` 键。

还可以检查 Cloud Code 日志，查看是否已执行 Cloud Code 脚本或模块。

1. 在 [Unity Dashboard](https://cloud.unity.com) 中，打开 **Cloud Code**。
2. 选择 **Logs（日志）**。

**Logs（日志）** 页面显示 `SchedulerHelloWorld` 模块或脚本的日志条目。
