处理跨玩家数据
Access and modify data for multiple players at once with Cloud Code modules.
阅读时间7 分钟最后更新于 1 个月前
您可以使用 Cloud Code 模块同时访问和修改多个玩家的数据。 这种功能解锁了多种用例,例如:
- 在 Cloud Save 中一次性为多个玩家更新玩家数据。
- 一次性向多个玩家发送推送通知。
- 一次性更新多个玩家的 Economy 余额。
获取玩家 ID
为了处理多个玩家的数据,您需要先调用 UGS 服务来获取玩家 ID。 为了获取玩家 ID,可以使用Com.Unity.Services.CloudCode.Apis使用 Leaderboards
首先,需要创建一个排行榜。 例如,可以从排行榜中获取前五名玩家并保存他们的 ID。以下模块接受一个排行榜 ID 并返回前五名玩家的分数列表:调用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()); } }}
GetTopPlayers{ "output": [ { "playerId": "wYI5NW5gEVvR3PBmYXEzFS1JvSz3", "playerName": "IncredibleGleamingPelican#3", "rank": 0, "score": 44.0 }, { "playerId": "ryuAA3ZX23aRHN5ZJClC1Z5BrpVb", "playerName": "EffectiveBindingBlackberry#9", "rank": 1, "score": 1.0 } ]}
使用 Lobby
首先,需要创建一个大厅。 您可以获取当前在大厅中的玩家列表,并使用他们的 ID 来处理他们的数据:调用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()); } }}
GetLobbyPlayers{ "output": [ { "allocationId": null, "connectionInfo": null, "data": null, "id": "Z96pNb4wfgdaMLqMQfWpwXEclaRR", "joined": "2023-09-08T11:02:18.13Z", "lastUpdated": "2023-09-08T11:02:18.13Z" } ]}
使用 Friends
为了使用 Friends,您需要创建一个关系。如需了解更多信息,请参阅 Friends 文档。
然后,可以获取玩家的好友列表,并使用他们的 ID 来处理他们的数据。以下示例显示了如何获取玩家已将好友请求发送到的玩家 ID 列表:
调用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()); } }}
GetRelationships{ "output": [ { "created": "2023-09-18T14:46:34.74Z", "expires": null, "id": "5774e898-a078-4f92-9f0a-4c9beeb6d1bb", "members": [ { "id": "0gvQingjjBwpZhkUJfeoKnFUkD4T" } ], "type": "FRIEND_REQUEST" } ]}
处理玩家数据
获得玩家 ID 列表后,您就可以使用它们通过 UGS 服务更新玩家数据。 以下示例显示了如何使用 Cloud Save 和 Economy 服务来处理玩家数据。以 Cloud Code 身份进行身份验证
要处理跨玩家数据,您需要以 Cloud Code 身份进行身份验证。要以 Cloud Code 身份进行身份验证,请在模块函数中使用ServiceTokenAccessToken请参阅身份验证以了解更多信息,并查看服务和访问令牌支持以获取支持await gameApiClient.CloudSaveData.SetItemAsync(ctx, ctx.ServiceToken, ctx.ProjectId, player.PlayerId, new SetItemBody("ReachedTop5", true));
ServiceToken使用 Cloud Save 更新前 5 名玩家数据
处理玩家数据的一种方法是将玩家 ID 列表传递给 Cloud Save。 示例中的模块函数将排行榜 ID 作为参数。 以下示例显示了针对从排行榜获取的前 5 名玩家列表,如何在 Cloud Save 中记录达到前 5 名的值。为了确保示例正常工作,请按照以下步骤操作:- 使用 Leaderboards 服务创建一个排行榜。
- 在排行榜上准备好一些玩家分数。
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()); } }}
UpdateTopPlayerData对大厅中所有使用 Economy 的玩家进行奖励
要处理玩家余额,您可以将玩家 ID 列表传递给 Economy API。 以下示例显示了如何增加从大厅中获取的玩家列表的货币余额。模块函数将大厅 ID、货币 ID 和余额增加金额作为参数。 为了确保示例正常工作,请按照以下步骤操作: 创建一个新模块并添加以下代码: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()); } }}
RewardLobbyPlayers