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 3 months 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 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.
key-savedThe 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.
- In the Unity Dashboard, open the Account menu and select Manage organization.
- In the Administration menu, select Service Accounts.
- Select the New button and enter a name and description for the Service Account.
- Select Create.
Add Product roles and create a key:
- 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
For more information, refer to Authentication.
Configure the UGS CLI
Follow the steps below to get started with 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
key-savedThe Cloud Save service emits a event when a Cloud Save key is saved. The event payload looks like this:
key-saved{ "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 module function with contents as below:
AnnounceLevelUpusing 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, IPushClient 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, IPushClient 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<IGameApiClient>(GameApiClient.Create()); config.Dependencies.AddSingleton<IPushClient>(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 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.
key-savedThe 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:
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 key.
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
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 as parameter.
lobbyIdJavaScript
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.
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 property.
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
MonobehaviourTo subscribe to player-level messages, set up a script.
Refer to Send push messages for more information.
MonobehaviourYou can use the sample code below for your script:
MonoBehaviourusing 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 script, it logs a player ID. Note this value down.
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 the parameter and player ID you noted down when running the Unity project as the parameter.
lobbyIdplayerIdUpdate the Level
key in Cloud Save
LevelYou can update the Cloud Save key to trigger the Cloud Code module by running the script below.
It takes in a string parameter and a number parameter .
playerIdlevelUse 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 key in Cloud Save.
LEVELYou 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!", }