Documentation

Support

Use case sample: Announce a level up to all players in joined lobbies

Announce a player's level up to all other players in joined lobbies through a push message.
Read time 7 minutesLast updated 18 hours ago

This use case sample demonstrates how to use Triggers to announce a player’s level up to all other players in any lobbies the player is in. The sample uses the
key-saved
event that the Cloud Save service emits. The sample notifies players who are in the same Lobby as the player who leveled about the level up through a push message.
The trigger uses a filter to evaluate the event payload so that the Cloud Code module only triggers when the player levels up and a player entity emits the Cloud Save event.

Prerequisites

You must first create a service account with required access roles.

Authenticate using a Service Account

Before you can call the Triggers service, you must authenticate using a Service Account.
  1. Navigate to the Unity 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 and Triggers Configuration Viewer.
    • 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 started 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. Use the Service account that you created to authenticate. Refer to Get Authenticated.

Examine the
key-saved
event

The Cloud Save service emits a
key-saved
event when a Cloud Save key is saved. The event payload looks like this:
{ "id": "7LpyhpsIvEczGkDI1r8J6gHhHezL", "idType": "player", "key": "LEVEL", "value": 1, "valueIncluded": true, "writeLock": "7b8920a57912509f6b5cbb183eb7fcb0", "accessClass": "default", "modifiedDate": "2021-03-04T09:00:00Z"}
The event passes the event payload to Cloud Code as parameters. Refer to Cloud Save: Key Saved for more information.

Set up Cloud Code

Define a module endpoint that sends a push message to all players in the lobby when a player levels up. Create a
AnnounceLevelUp
module function with contents as below:
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.Lobby.Model;namespace AnnounceLevelUp;public class AnnounceLevelUp{ private const string ServiceId = "cloud-code"; private readonly ILogger<AnnounceLevelUp> _logger; public AnnounceLevelUp(ILogger<AnnounceLevelUp> logger) { _logger = logger; } [CloudCodeFunction("AnnounceLevelUp")] public async Task Announce(IExecutionContext ctx, PushClient pushClient, IGameApiClient gameApiClient, string id) { try { var playerList = await GetPlayersFromLobbies(ctx, gameApiClient, id); if (playerList.Count == 0) { _logger.LogInformation("The player {playerId} has not joined any lobbies", id); return; } await SendPushMessage(ctx, pushClient, playerList); } catch (ApiException e) { _logger.LogError("Failed to announce level up for player {playerId}. Error: {Error}", id, e.Message); throw new Exception($"Failed to announce level up for player {id}. Error: {e.Message}"); } } public async Task SendPushMessage(IExecutionContext ctx, PushClient pushClient, List<Player> lobbyPlayers) { foreach (var lobbyPlayer in lobbyPlayers) { try { var message = $"The player {lobbyPlayer.Id} has leveled up!"; _logger.LogInformation("Sending push notification to player {lobbyPlayer}", lobbyPlayer.Id); await pushClient.SendPlayerMessageAsync(ctx, message, "Level up!", lobbyPlayer.Id); } catch (ApiException e) { _logger.LogError("Failed to send push notification to player {playerId}. Error: {Error}", lobbyPlayer.Id, e.Message); } } } public async Task<List<Player>> GetPlayersFromLobbies(IExecutionContext ctx, IGameApiClient gameApiClient, string playerId) { var playersToNotify = new List<Player>(); try { var lobbyList = await gameApiClient.Lobby.GetJoinedLobbiesAsync(ctx, ctx.ServiceToken, ServiceId,playerId ); foreach (var lobby in lobbyList.Data) { var players = await GetLobbyData(ctx, gameApiClient, lobby); playersToNotify.AddRange(players); } return playersToNotify; } catch (Exception e) { _logger.LogError("Failed to get players from lobbies. Error: {Error}", e.Message); throw new Exception($"Failed to get players from lobbies. Error: {e.Message}"); } } public async Task<List<Player>> GetLobbyData(IExecutionContext ctx, IGameApiClient gameApiClient, string lobbyId) { try { var response = await gameApiClient.Lobby.GetLobbyAsync(ctx, ctx.ServiceToken, lobbyId, "cloud-code"); return response.Data.Players; } catch (Exception e) { _logger.LogError("Failed to get players from lobby: {lobbyId}. Error: {Error}", lobbyId, e.Message); throw new Exception($"Failed to get players from lobby: {lobbyId}. Error: {e.Message}"); } } public class ModuleConfig : ICloudCodeSetup { public void Setup(ICloudCodeConfig config) { config.Dependencies.AddSingleton(GameApiClient.Create()); config.Dependencies.AddSingleton(PushClient.Create()); } }}
Deploy the module. Refer to Deploying Hello World to learn how to deploy a module.

Configure a trigger

To connect your Cloud Code resource to the Cloud Save
key-saved
event, create a trigger. The trigger executes the Cloud Code module when the event is fired, for example, every time a player saves a key.
The filter in the trigger configuration evaluates the event payload to only trigger the Cloud Code module when the player levels up and the Cloud Save event is emitted by a player entity.
  1. Run the
    new-file
    command to create a trigger configuration locally:
ugs triggers new-file triggers-config
  1. Update the
    triggers-config.tr
    file with the following configuration:
{ "$schema": "https://ugs-config-schemas.unity3d.com/v1/triggers.schema.json", "Configs": [ { "Name": "announce-level-up", "EventType": "com.unity.services.cloud-save.key-saved.v1", "ActionUrn": "urn:ugs:cloud-code:AnnounceLevelUp/AnnounceLevelUp", "ActionType": "cloud-code", "Filter": "data[\"idType\"] == \"player\" && data[\"key\"] == \"LEVEL\"" } ]}
  1. Deploy the configuration using the UGS CLI tool:
ugs deploy triggers-config.tr
You should get a response similar to the following:
Deployed:triggers-config.tr
The sample trigger executes your Cloud Code module function when a player saves a value to the
LEVEL
key.

Set up Lobby

To follow the sample, you need to create a Lobby. You can use a helper Cloud Code script from the Unity Dashboard. to achieve this:

JavaScript

const { LobbyApi } = require("@unity-services/lobby-1.2");module.exports = async ({ params, context, logger }) => { const lobbyApi = new LobbyApi(context); const serviceId = "cloud-code"; try { // Create a private lobby without any initial players. const { data: lobby } = await lobbyApi.createLobby(serviceId, null, { name: "sample-lobby", maxPlayers: 4, }); return lobby.id; } catch (err) { logger.error(`Error while calling out to Lobby: ${JSON.stringify(err.message)}`); throw err; }};
Note down the lobby ID.

Add players to a lobby

You can run the following Cloud Code script to add players to the lobby you created from the Unity Dashboard. Make sure to select the Generate icon to regenerate the Player ID token on every test run to add a new player. Note down one of the player ID of the player you added to the lobby. You can use this later to validate the result by updating their Cloud Save data. The script takes in
lobbyId
as parameter.

JavaScript

const { LobbyApi } = require("@unity-services/lobby-1.2");module.exports = async ({ params, context, logger }) => { const lobbyApi = new LobbyApi(context); const serviceId = "cloud-code"; try { await lobbyApi.joinLobbyById(params.lobbyId, serviceId, context.playerId); } catch (err) { logger.error("Failed to join lobby", { "error.message": err.message }, { lobbyId: params.lobbyId }); throw err; }};

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 for adding players you created earlier to make the authenticated player join a lobby.

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 project

Link your Unity Gaming Services project with the Unity Editor. You can find your UGS project ID in the Unity 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 with the
UnityEditor.CloudProjectSettings.projectId
property.

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.

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:
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. Note this value down.

Join a lobby

You can use the Cloud Code script for adding players you created earlier to make the authenticated player join a lobby. Pass in the lobby ID you created earlier as the
lobbyId
parameter and player ID you noted down when running the Unity project as the
playerId
parameter.

Update the
Level
key in Cloud Save

You can update the Cloud Save key to trigger the Cloud Code module by running the script below. It takes in a string parameter
playerId
and a number parameter
level
.
Use the player ID of one of the players you added to the lobby earlier. This ensures that the player authenticated in the Unity project receives the message, as they are in the same lobby.

JavaScript

const { DataApi } = require("@unity-services/cloud-save-1.4");module.exports = async ({ params, context, logger }) => { const cloudSaveApi = new DataApi(context); try { await cloudSaveApi.setItem(context.projectId, params.playerId, { key: "LEVEL", value: params.level, }); result = await cloudSaveApi.getItems(context.projectId, params.playerId); return result.data; } catch (err) { logger.error("Error while calling out to Cloud Save", { "error.message": err.message }); throw err; }};

Validate the result

Ensure that the Unity project is running, the authenticated player in your Unity project is in a lobby, and update the
LEVEL
key in Cloud Save.
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-11-13T16:21:35.102058117Z", "message": "The player Z96pNb4wfgdaMLqMQfWpwXEclaRZ has leveled up!", "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": "Level up!",}