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-savedPrerequisites
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.- Navigate to the Unity Dashboard.
- Select Administration > Service Accounts.
- Select the New button and enter a name and description for the Service Account.
- Select Create.
- Select Manage product roles.
- 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.
- From the LiveOps dropdown, select Triggers Configuration Editor and Triggers Configuration Viewer.
- Select Save.
- Select Add Key.
- Encode the Key ID and Secret key using base64 encoding. The format is . Note this value down.
key_id:secret_key
Configure the UGS CLI
Follow the steps below to get started with the UGS CLI:- Install the UGS CLI.
-
Configure your Project ID and Environment as such:
ugs config set project-id <your-project-id>
ugs config set environment-name <your-environment-name> - 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-savedkey-savedThe event passes the event payload to Cloud Code as parameters. Refer to Cloud Save: Key Saved for more information.{ "id": "7LpyhpsIvEczGkDI1r8J6gHhHezL", "idType": "player", "key": "LEVEL", "value": 1, "valueIncluded": true, "writeLock": "7b8920a57912509f6b5cbb183eb7fcb0", "accessClass": "default", "modifiedDate": "2021-03-04T09:00:00Z"}
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 aAnnounceLevelUpDeploy the module. Refer to Deploying Hello World to learn how to deploy a module.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()); } }}
Configure a trigger
To connect your Cloud Code resource to the Cloud Savekey-saved
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.
- Run the command to create a trigger configuration locally:
new-file
ugs triggers new-file triggers-config
- Update the file with the following configuration:
triggers-config.tr
{ "$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\"" } ]}
- Deploy the configuration using the UGS CLI tool:
You should get a response similar to the following:ugs deploy triggers-config.tr
The sample trigger executes your Cloud Code module function when a player saves a value to theDeployed:triggers-config.tr
LEVELSet 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
Note down the lobby ID.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; }};
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 inlobbyIdJavaScript
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.- In Unity Editor, select Edit > Project Settings > Services.
-
Link your project.
If your project doesn't have a Unity project ID:- Select Create a Unity Project ID > Organizations, then select an organization from the dropdown.
- Select Create project ID.
If you have an existing Unity project ID:- Select Use an existing Unity project ID.
- Select an organization and a project from the dropdowns.
- Select Link project ID.
UnityEditor.CloudProjectSettings.projectIdSDK installation
To install the latest Cloud Code package for Unity Editor:- In the Unity Editor, open Window > Package Manager.
- In the Package Manager, select the Unity Registry list view.
- Search for , or locate the Cloud Code package in the list.
com.unity.services.cloudcode - Select the package, then select Install.
Create a Monobehaviour
script
To subscribe to player-level messages, set up a MonobehaviourMonobehaviourMonoBehaviourThe first time you run theusing 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); } }}
MonobehaviourJoin 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 thelobbyIdplayerIdUpdate 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 LevelplayerIdlevel
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 theLEVELGot 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!",}