Documentation

Support

Interact with cross-player data

Access and modify data for multiple players at once with Cloud Code modules.
Read time 6 minutesLast updated 18 hours ago

You can use Cloud Code modules to access and modify data for multiple players at once. This unlocks a variety of use cases, such as to:
  • Update the player data in Cloud Save for multiple players at once.
  • Send a push notification to multiple players at once.
  • Update Economy balances for multiple players at once.

Retrieve player IDs

To interact with multiple players, you need call to UGS services to retrieve the player IDs first. To get the player IDs, you can use the Cloud Code C# SDKs in the
Com.Unity.Services.CloudCode.Apis
NuGet package.
You can also use a service's REST API directly. Services that you can use to get player IDs include Leaderboards, Lobby, and Friends.

Use Leaderboards

First, you need to create a Leaderboard. For example, you can retrieve the top five players from a leaderboard and save their IDs. The module below takes in a leaderboard ID and returns a list of top five players' scores:
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.Leaderboards.Model;namespace CrossPlayerData;public class CrossPlayerData{ private readonly ILogger<CrossPlayerData> _logger; public CrossPlayerData(ILogger<CrossPlayerData> logger) { _logger = logger; } [CloudCodeFunction("GetTopPlayers")] public async Task<List<LeaderboardEntry>> GetTopPlayers(IExecutionContext ctx, IGameApiClient gameApiClient, string leaderboardId) { ApiResponse<LeaderboardScoresPage> response; try { response = await gameApiClient.Leaderboards.GetLeaderboardScoresAsync(ctx, ctx.ServiceToken, new Guid(ctx.ProjectId), leaderboardId, null, 5); return response.Data.Results; } catch (ApiException e) { _logger.LogError("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(GameApiClient.Create()); } }}
Call the
GetTopPlayers
function to retrieve a list of top 5 players. The response looks similar to below:
{ "output": [ { "playerId": "wYI5NW5gEVvR3PBmYXEzFS1JvSz3", "playerName": "IncredibleGleamingPelican#3", "rank": 0, "score": 44.0 }, { "playerId": "ryuAA3ZX23aRHN5ZJClC1Z5BrpVb", "playerName": "EffectiveBindingBlackberry#9", "rank": 1, "score": 1.0 } ]}

Use Lobby

First, you need to create a Lobby. You can retrieve a list of players that are currently in the Lobby, and use their IDs to interact with their data:
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 CrossPlayerData;public class CrossPlayerData{ private readonly ILogger<CrossPlayerData> _logger; public CrossPlayerData(ILogger<CrossPlayerData> logger) { _logger = logger; } [CloudCodeFunction("GetLobbyPlayers")] public async Task<List<Player>> GetLobby(IExecutionContext ctx, IGameApiClient gameApiClient, string lobbyId) { ApiResponse<Lobby> response; try { response = await gameApiClient.Lobby.GetLobbyAsync(ctx, ctx.ServiceToken, lobbyId, "cloud-code"); return response.Data.Players; } catch (ApiException 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()); } }}
Call the
GetLobbyPlayers
function to retrieve a list of players in the lobby.
The response looks similar to below:
{ "output": [ { "allocationId": null, "connectionInfo": null, "data": null, "id": "Z96pNb4wfgdaMLqMQfWpwXEclaRR", "joined": "2023-09-08T11:02:18.13Z", "lastUpdated": "2023-09-08T11:02:18.13Z" } ]}

Use Friends

To use Friends, you need to create a relationship. For more information, see the Friends documentation. You can then retrieve a list of friends for a player, and use their IDs to interact with their data. The sample below shows how you can retrieve a list of player IDs that a player has sent friend requests to:
using Microsoft.Extensions.DependencyInjection;using Microsoft.Extensions.Logging;using Unity.Services.CloudCode.Apis;using Unity.Services.CloudCode.Core;using Unity.Services.Friends.Model;namespace CrossPlayerData;public class CrossPlayerData{ private readonly ILogger<CrossPlayerData> _logger; public CrossPlayerData(IExecutionContext ctx, ILogger<CrossPlayerData> logger) { _logger = logger; } [CloudCodeFunction("SendFriendRequest")] public async Task SendFriendRequest(IExecutionContext ctx, IGameApiClient gameApiClient, string playerId) { try { await gameApiClient.FriendsRelationshipsApi.CreateRelationshipAsync( ctx, ctx.AccessToken, false, false, new AddRelationshipRequest(RelationshipType.FRIENDREQUEST, new List<MemberIdentity> { new(id : playerId) })); } catch (Exception e) { _logger.LogError("Failed to send a friend request to playerId: {playerId}. Error: {Error}", playerId, e.Message); throw new Exception("Failed to send a friend request to playerId: " + playerId + ". Error: " + e.Message); } } [CloudCodeFunction("GetRelationships")] public async Task<List<Relationship>> GetRelationships(IExecutionContext ctx, IGameApiClient gameApiClient) { try { var res = await gameApiClient.FriendsRelationshipsApi.GetRelationshipsAsync(ctx, ctx.AccessToken, 10, 0, false, false); return res.Data; } catch (Exception e) { _logger.LogError("Failed to get relationships for playerId: {playerId}. Error: {Error}", ctx.PlayerId, e.Message); throw new Exception("Failed to get relationships for playerId: " + ctx.PlayerId + ". Error: " + e.Message); } } public class ModuleConfig : ICloudCodeSetup { public void Setup(ICloudCodeConfig config) { config.Dependencies.AddSingleton(GameApiClient.Create()); } }}
Call the
GetRelationships
function to retrieve a list of players that the player has sent friend requests to.
The response looks similar to below:
{ "output": [ { "created": "2023-09-18T14:46:34.74Z", "expires": null, "id": "5774e898-a078-4f92-9f0a-4c9beeb6d1bb", "members": [ { "id": "0gvQingjjBwpZhkUJfeoKnFUkD4T" } ], "type": "FRIEND_REQUEST" } ]}

Interact with player data

Once you have a list of player IDs, you can use them to update player data through UGS services. The samples below show how to use the Cloud Save and Economy services to interact with player data.

Authenticate as Cloud Code

To interact with cross-player data, you need to authenticate as Cloud Code. To authenticate as Cloud Code, use the
ServiceToken
instead of the
AccessToken
in the module function:
await gameApiClient.CloudSaveData.SetItemAsync(ctx, ctx.ServiceToken, ctx.ProjectId, player.PlayerId, new SetItemBody("ReachedTop5", true));
Refer to Authentication for more information and check Service and access token support for a list of services that support the
ServiceToken
.

Update top 5 player data using Cloud Save

One way to interact with player data is to pass in a list of player IDs to Cloud Save. The module function in the sample takes a leaderboard ID as a parameter. The sample below shows how to record a value for reaching top 5 in Cloud Save for a list of top 5 players retrieved from a leaderboard. To ensure the sample works, follow the steps below:
  1. Create a leaderboard using the Leaderboards service.
  2. Have some player scores on the leaderboard.
Create a new module and add the following code:
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 CrossPlayerData;public class CrossPlayerData{ private readonly ILogger<CrossPlayerData> _logger; public CrossPlayerData(ILogger<CrossPlayerData> logger) { _logger = logger; } [CloudCodeFunction("GetTopPlayers")] public async Task<List<LeaderboardEntry>> GetTopPlayers(IExecutionContext ctx, IGameApiClient gameApiClient, string leaderboardId) { ApiResponse<LeaderboardScoresPage> response; try { response = await gameApiClient.Leaderboards.GetLeaderboardScoresAsync(ctx, ctx.ServiceToken, new Guid(ctx.ProjectId), leaderboardId, null, 5); return response.Data.Results; } catch (ApiException e) { _logger.LogError("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}"); } } [CloudCodeFunction("UpdateTopPlayerData")] public async Task UpdateTopPlayerData(IExecutionContext ctx, IGameApiClient gameApiClient, string leaderboardId) { var players = GetTopPlayers(ctx, gameApiClient, leaderboardId); foreach (var player in players.Result) { try { await gameApiClient.CloudSaveData.SetItemAsync(ctx, ctx.ServiceToken, ctx.ProjectId, player.PlayerId, new SetItemBody("ReachedTop5", true)); _logger.LogInformation("Updated data for playerId {playerId}", player.PlayerId); } catch (Exception e) { _logger.LogError("Failed to update data for playerId {playerId}. Error: {Error}", player.PlayerId, e.Message); throw new Exception ($"Failed to update data for playerId: {player.PlayerId}. Error: {e.Message}"); } } } public class ModuleConfig : ICloudCodeSetup { public void Setup(ICloudCodeConfig config) { config.Dependencies.AddSingleton(GameApiClient.Create()); } }}
The
UpdateTopPlayerData
function sets a key-value pair for all players in the leaderboard. To verify this, you can navigate to the Player Management service in the Unity Dashboard and inspect the Cloud Save data for the top players.

Reward all players in the Lobby using Economy

To interact with player balances, you can pass in a list of player IDs to the Economy API. The sample below shows how to increment the balance of a currency for a list of players retrieved from a lobby. The module function takes in a lobby ID, currency ID, and an amount to increment the balance by as parameters. To ensure the sample works, follow the steps below:
  1. Create a lobby using the Lobby service.
  2. Have a player in the lobby.
  3. Create and publish a currency in the Economy service.
Create a new module and add the following code:
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.Economy.Model;using Unity.Services.Lobby.Model;public class CrossPlayerData{ private readonly ILogger<CrossPlayerData> _logger; public CrossPlayerData(ILogger<CrossPlayerData> logger) { _logger = logger; } [CloudCodeFunction("GetLobbyPlayers")] public async Task<List<Player>> GetLobby(IExecutionContext ctx, IGameApiClient gameApiClient, string lobbyId) { ApiResponse<Lobby> response; try { 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}"); } } [CloudCodeFunction("RewardLobbyPlayers")] public async Task RewardLobbyPlayers(IExecutionContext ctx, IGameApiClient gameApiClient, string lobbyId, string currencyId, int amount) { var players = GetLobby(ctx, gameApiClient, lobbyId); foreach (var player in players.Result) { try { await gameApiClient.EconomyCurrencies.IncrementPlayerCurrencyBalanceAsync(ctx, ctx.ServiceToken, ctx.ProjectId, player.Id, currencyId, new CurrencyModifyBalanceRequest(currencyId, amount)); _logger.LogInformation("Incremented balance for playerId {playerId} by {amount}", player.Id, amount); } catch (Exception e) { _logger.LogError("Failed to increment {currencyId} balance for playerId {playerId}. Error: {Error}", currencyId, player.Id, e.Message); throw new Exception($"Failed to increment {currencyId} balance for playerId {player.Id}. Error: {e.Message}"); } } } public class ModuleConfig : ICloudCodeSetup { public void Setup(ICloudCodeConfig config) { config.Dependencies.AddSingleton(GameApiClient.Create()); } }}
The
RewardLobbyPlayers
function increments the balance of the currency for all players in the lobby.
To verify, you can navigate to the Player Management service in the Unity Dashboard and inspect the balances for your players.