# Get started

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

This section describes all the steps you need to get started with Triggers.

The walkthrough below uses a **Cloud Code** action (a script or module that runs when an event fires). If you prefer to send events to an external URL instead, refer to [Webhooks](/triggers/webhooks.md) and [Use case sample: Notify a Discord channel](./tutorials/use-cases/notify-discord-channel).

The sample below demonstrates how to use Triggers to reward the top five players from [Leaderboards](/leaderboards.md) with a seasonal trophy in [Cloud Save](/cloud-save.md) using a one-time schedule event emitted by the Scheduler.

## Video walkthrough

Watch the video below for a walkthrough of the steps to create a trigger in the Unity Dashboard.


**Frame:**

[Getting started with Triggers](https://www.youtube.com/embed/eTnxB3OczOY?si=ywbe6sEj_mN7XYYo)

## Typical workflow

To get started with Triggers, follow these steps:

1. [Create a Cloud Code script or module to be run on event:](#set-up-cloud-code) Define game logic to execute when the event is fired.
2. [Schedule an event to change the state of a resource:](#schedule-an-event) Define when the event is fired.
3. [Configure a trigger to execute the Cloud Code module endpoint on event:](#configure-a-trigger) Define which Cloud Code script or module is executed when the event is fired (or use a [webhook](/triggers/webhooks.md) to send the event to an external URL).
4. [Validate the result:](#validate-the-result) Check that the Cloud Code script or module has been executed.

> **Note:**
>
> You can also use the Triggers with events emitted by other services. Refer to the [Events](./manage-events/events) section for more information.

## Prerequisites

The steps assume you have already created a [Unity Gaming Services project in the Unity Dashboard](/cloud/projects/create-project.md).

You must first create a service account with required access roles and configure the [UGS CLI](https://services.docs.unity.com/guides/ugs-cli/latest/general/get-started/install-the-cli/).

### Authenticate using a Service Account

Before you can call the Scheduling and Triggers services, you must authenticate using a Service Account.

1. Navigate to the [Unity Dashboard](https://cloud.unity.com).
2. Select **Administration** > **Service Accounts**.
3. Select the **New** button and enter a name and description for the Service Account.
4. Select **Create**.

Add Product roles and create a key:

1. Select **Manage product roles**.
2. Add the following roles to the Service Account:
   * From the LiveOps dropdown, select **Triggers Configuration Editor**, **Triggers Configuration Viewer**, **Scheduler Configuration Editor**, **Scheduler Configuration Viewer**, and **Leaderboards Admin**.
   * From the Admin dropdown, select **Unity Environments Viewer**.
3. Select **Save**.
4. Select **Add Key**.
5. Encode the **Key ID** and **Secret key** using base64 encoding. The format is “key\_id:secret\_key”. Note this value down.

For more information, refer to [Authentication](./authentication).

### Configure the UGS CLI

Follow the steps below to get stated with the UGS CLI:

1. [Install the UGS CLI](https://services.docs.unity.com/guides/ugs-cli/latest/general/get-started/install-the-cli/).

2. Configure your Project ID and Environment as such:
   `ugs config set project-id <your-project-id>`
   `ugs config set environment-name <your-environment-name>`

3. Authenticate using the Service account you created earlier. Refer to [Get Authenticated](https://services.docs.unity.com/guides/ugs-cli/latest/general/get-started/get-authenticated/).

### Set up Leaderboards

To follow this sample, you should create a leaderboard.

You can use the UGS CLI to deploy the following `leaderboard.lb` file. It defines a leaderboard with ascending sort order and keeps the best score.

Run the `new-file` command to create a leaderboard configuration locally:

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

The file name corresponds to the leaderboard ID. Update the `leaderboard.lb` file with the following configuration:

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

Deploy the file using the UGS CLI tool:

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

Now that you have created a leaderboard, you can add scores to it.

### Optional: Add scores to the leaderboard

You can run the following Cloud Code script to add scores to the leaderboard from the [Unity Dashboard.](https://cloud.unity.com)
Make sure to regenerate the Player ID token on every test run to generate a score for a new player.

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

## Set up Cloud Code

To use Triggers, you should define a Cloud Code module or a Cloud Code script. The module or script is executed when a trigger is fired.
The sample below integrates [Leaderboards](/leaderboards.md) and [Cloud Save](/cloud-save.md) with Cloud Code to reward the top five players from the leaderboard with a seasonal trophy.

### Cloud Code C# module

Define a `SchedulerHelloWorld` module with a function that takes in string arguments `key` and `value`.

The module endpoint `RewardPlayers` retrieves the top five players from the leaderboard and sets the Cloud Save data for each player with the
specified key and value.

```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<IGameApiClient>(GameApiClient.Create());
        }
    }

}
```

Deploy the module.

Refer to [Deploying Hello World](/cloud-code/scripts/getting-started.md#deploying-hello-world) to learn how to deploy a module.

> **Note:**
>
> If you are deploying the module using the UGS CLI, don't forget to add additional Service Account role of `Cloud Code Editor`.

### Cloud Code JavaScript script

You can achieve the same outcome by creating a Cloud Code script.

Create a `SchedulerHelloWorld` script with required string arguments `key` and `value`:

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

Publish the script.

Refer to [Deploying Hello World](/cloud-code/scripts/getting-started.md#deploying-hello-world) to learn how to deploy a script.

> **Note:**
>
> If you are deploying the script using the UGS CLI, don't forget to add additional Service Account roles: `Cloud Code Script Publisher` and `Cloud Code Editor`.

## Schedule an event

After you have defined your Cloud Code script or module, you can create a schedule to determine when the top five players are rewarded with a trophy.

The sample below defines a one-time schedule that grant players a seasonal trophy.

Run the `new-file` command to create a schedule configuration locally:

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

Update the `schedule-config.sched` file with the following configuration:

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

The `payload` of the event carries the Cloud Code parameters that are passed to the Cloud Code script or module.
Modify the `schedule` field to change the date and time when the event is triggered.

Deploy the configuration using the UGS CLI tool:

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

You should get a response similar to the following:

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

Now you have a schedule that triggers an event at a specific time. However, the events are not yet connected to your Cloud Code script or module.

## Configure a trigger

To connect your Cloud Code resource to the schedule, create a trigger. The trigger executes the Cloud Code module or script when the event is fired, for example, when the schedule is triggered.

Run the `new-file` command to create a trigger configuration locally:

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

If you created a Cloud Code module, update the `triggers-config.tr` file with the following configuration:

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

If you created a Cloud Code script, update the `triggers-config.tr` file with the following configuration:

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

Deploy the configuration using the UGS CLI tool:

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

You should get a response similar to the following:

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

Now you have a trigger that executes your Cloud Code script or module when the event is fired.

## Validate the result

To validate the result, you can inspect the top players before and after the event is fired.

1. Navigate to the [Unity Dashboard](https://cloud.unity.com).
2. Select **Products** > **Leaderboards**.
3. Select the **Overview** section.
4. Select the `leaderboard` leaderboard.
5. Select the **Entries** tab.
6. Note down one of the top player IDs.

To validate that the player data has been updated, you can check the Cloud Save data for the player:

1. From the [Unity Dashboard](https://cloud.unity.com), select **Products** > **Player Management**.
2. In the search field, enter the player ID you noted down earlier and select **Find Player**.
3. Navigate to the **Cloud Save** > **Data** section.
4. You should find the `seasonal-trophy` key with the value `2023-08-28`.

You can also inspect the Cloud Code logs to check that the Cloud Code script or module has been executed.

1. In the [Unity Dashboard](https://cloud.unity.com), open **Cloud Code**.
2. Select **Logs**.

The **Logs** page shows log entries from the `SchedulerHelloWorld` module or script.
