Use case sample: Send a push message to the player whose score was beaten

The use case sample demonstrates how to use Triggers to send a push message to a player whose score was beaten in a leaderboard. The sample uses the score-submitted event from the Leaderboards service.

Note: You can only use push messages with Cloud Code modules.

Prerequisites

You must first create a service account with required access roles and configure the UGS CLI.

Authenticate using a Service Account

Before you can call the Triggers service, you must authenticate using a Service Account.

  1. Navigate to the Unity Cloud Dashboard.
  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, 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.

Configure the UGS CLI

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

  1. Install the UGS 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.

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:

ugs leaderboards new-file leaderboard

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

{
  "$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:

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 Cloud Dashboard. Make sure to regenerate the Player ID token on every test run to generate a score for a new player.

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

Examine the score-submitted event

The Leaderboards service emits a score-submitted event when a new score is submitted to a leaderboard. The event payload looks like this:

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

The event passes the event payload to Cloud Code as parameters.

Refer to Leaderboards: Score Submitted for more information.

Set up Cloud Code

Define a module endpoint that sends a push message to the player whose score was beaten.

Create a SendPushNotification module function with contents as below:

C#

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

Deploy the module.

Refer to 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.

Configure a trigger

To connect your Cloud Code resource to the Leaderboards score-submitted event, create a trigger. The trigger executes the Cloud Code module when the event is fired, for example, every time a new score is submitted.

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

ugs triggers new-file triggers-config

Update the triggers-config.tr file with the following configuration:

{
  "$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"
    }
  ]
}

Deploy the configuration using the UGS CLI tool:

ugs deploy triggers-config.tr

A successful response is similar to the following:

Deployed:
    triggers-config.tr

The sample trigger executes your Cloud Code module function when a player signs up.

Validate the result

To validate the result, you can set up a Unity project that subscribes to push messages and use the Cloud Code script you created earlier to submit a new score to the leaderboard.

Prerequisites

To subscribe to push messages, you need to install the Cloud Code SDK and link your Unity Gaming Services project to the Unity Editor.

Link your Unity Gaming Services project with the Unity Editor. You can find your UGS project ID in the Unity Cloud Dashboard.

  1. In Unity Editor, select Edit > Project Settings > Services.

  2. Link your project.
    If your project doesn't have a Unity project ID:

    1. Select Create a Unity Project ID > Organizations, then select an organization from the dropdown.
    2. Select Create project ID.


    If you have an existing Unity project ID:

    1. Select Use an existing Unity project ID.
    2. Select an organization and a project from the dropdowns.
    3. Select Link project ID.

Your Unity Project ID appears, and the project is now linked to Unity services. You can also access your project ID in a Unity Editor script using UnityEditor.CloudProjectSettings.projectId.

SDK installation

To install the latest Cloud Code package for Unity Editor:

  1. In the Unity Editor, open Window > Package Manager.
  2. In the Package Manager, select the Unity Registry list view.
  3. Search for com.unity.services.cloudcode, or locate the Cloud Code package in the list.
  4. Select the package, then select Install.

Check Unity - Manual: Package Manager window to familiarize yourself with the Unity Package Manager interface.

You can subscribe to messages with Cloud Code SDK versions 2.4.0+.

Create a Monobehaviour script

To subscribe to player-level messages, set up a Monobehaviour script. Refer to Send push messages for more information.

You can use the sample code below for your MonoBehaviour script:

C#

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

The first time you run the Monobehaviour script, it logs a player ID. You can modify your Cloud Code script to submit a score for the specified ID to add the player to the leaderboard.

Run the script again to generate scores for the leaderboard.

You should encounter a push message sent when your player score is beaten in the Unity Editor:

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