使用示例:向加入大厅的所有玩家宣布升级
Announce a player's level up to all other players in joined lobbies through a push message.
阅读时间9 分钟最后更新于 1 个月前
此使用示例演示了如何使用 Triggers 向玩家所在大厅中的所有其他玩家宣布该玩家升级了。此示例使用了 Cloud Save 服务发出的
key-saved先决条件
必须首先创建具有所需访问角色的服务帐户。使用服务帐户进行身份验证
在调用 Triggers 服务之前,必须使用服务帐户进行身份验证。- 导航到 Unity Dashboard。
- 选择 Administration(管理)> Service Accounts(服务帐户)。
- 选择 New(新建) 按钮并输入服务帐户的名称和描述。
- 选择 Create(创建)。
- 选择 Manage product roles(管理产品角色)。
- 将以下角色添加到服务帐户:
- 从 LiveOps 下拉选单中,选择 Triggers Configuration Editor(Triggers 配置编辑者) 和 Triggers Configuration Viewer(Triggers 配置查看者)。
- 从 Admin(管理)下拉选单中,选择 Unity Environments Viewer(Unity 环境查看者)。
- 从 LiveOps 下拉选单中,选择 Triggers Configuration Editor(Triggers 配置编辑者) 和 Triggers Configuration Viewer(Triggers 配置查看者)。
- 选择 Save(保存)。
- 选择 Add Key(添加密钥)。
- 使用 base64 编码方式对 Key ID(密钥 ID) 和 Secret key(密钥) 进行编码。格式为“key_id:secret_key”。请记下此值。
检查 key-saved 事件
当保存 Cloud Save 键时,Cloud Save 服务会发出key-saved该事件会将事件有效负载作为参数传递给 Cloud Code。 请参阅 Cloud Save:保存键以了解更多信息。{ "id": "7LpyhpsIvEczGkDI1r8J6gHhHezL", "idType": "player", "key": "LEVEL", "value": 1, "valueIncluded": true, "writeLock": "7b8920a57912509f6b5cbb183eb7fcb0", "accessClass": "default", "modifiedDate": "2021-03-04T09:00:00Z"}
设置 Cloud Code
定义一个模块终端,当玩家升级时,向大厅中的所有玩家发送推送消息。 创建一个包含如下内容的AnnounceLevelUp部署该模块。 请参阅部署 Hello World 以了解如何部署模块。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()); } }}
配置触发器
要将 Cloud Code 资源关联到 Cloud Savekey-savedkey_id:secret_key此示例触发器会在玩家将值保存到curl 'https://services.api.unity.com/triggers/v1/projects/<PROJECT_ID>/environments/<ENVIRONMENT_ID>/configs' \--header 'Content-Type: application/json' \--header 'Authorization: Basic <SERVICE_ACCOUNT_CREDENTIALS_ENCODED>' \--data '{ "name": "announce-level-up", "eventType": "com.unity.services.cloud-save.key-saved.v1", "actionType": "cloud-code", "actionUrn": "urn:ugs:cloud-code:AnnounceLevelUp/AnnounceLevelUp", "filter": "data[\"idType\"] == \"player\" && data[\"key\"] == \"LEVEL\""}'
LEVEL设置大厅
为了按照示例操作,您需要创建一个大厅。您可以在 Unity Cloud Dashboard 中使用 Cloud Code 辅助脚本来实现此目的:JavaScript
记下大厅 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; }};
向大厅添加玩家
您可以运行以下 Cloud Code 脚本,将玩家添加到从 Unity Cloud Dashboard 创建的大厅。请确保在每次测试运行时重新生成玩家 ID 令牌,以便添加新玩家。
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; }};
验证结果
要验证结果,您可以设置一个订阅推送消息的 Unity 项目,并使用您先前创建的用于添加玩家的 Cloud Code 脚本,让经过身份验证的玩家加入大厅。先决条件
要订阅推送消息,需要安装 Cloud Code SDK,并将 Unity Gaming Services(Unity 游戏服务)项目关联到 Unity 编辑器。关联项目
将 Unity Gaming Services(Unity 游戏服务)项目与 Unity 编辑器关联。您可以在 Unity Cloud Dashboard 中找到您的 UGS Project ID。- 在 Unity 编辑器中,选择 Edit(编辑)> Project Settings(项目设置)> Services(服务)。
-
关联您的项目。
如果项目没有 Unity Project ID:- 选择 Create a Unity Project ID(创建 Unity Project ID)> Organizations(组织),然后从下拉选单中选择一个组织。
- 选择 Create project ID(创建 Project ID)。
如果已有 Unity Project ID:- 选择 Use an existing Unity project ID(使用现有 Unity Project ID)。
- 从下拉选单中选择组织和项目。
- 选择 Link project ID(关联 Project ID)。
UnityEditor.CloudProjectSettings.projectIdSDK 安装
要安装适用于 Unity 编辑器的最新 Cloud Code 包,请执行以下操作:- 在 Unity 编辑器中,打开 Window(窗口)> Package Manager(包管理器)。
- 在 Package Manager(包管理器)中,选择 Unity Registry(Unity 注册表) 列表视图。
- 搜索 或在列表中找到 Cloud Code 包。
com.unity.services.cloudcode - 选择该包,然后选择 Install(安装)。
创建 Monobehaviour 脚本
要订阅玩家级消息,请设置一个MonobehaviourMonoBehaviour首次运行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); } }}
Monobehaviour加入大厅
您可以使用先前创建的用于添加玩家的 Cloud Code 脚本,让经过身份验证的玩家加入大厅。将先前创建的大厅 ID 作为lobbyIdplayerId更新 Cloud Save 中的 Level 键
您可以运行以下脚本来更新 Cloud Save 键以触发 Cloud Code 模块。 它接受一个字符串参数playerIdlevel
请使用您先前添加到大厅的玩家的其中一个玩家 ID。这样可确保在 Unity 项目中经过身份验证的玩家会收到消息,因为他们在同一个大厅。
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; }};
验证结果
确保 Unity 项目正在运行,Unity 项目中经过身份验证的玩家位于大厅内,并更新 Cloud Save 中的LEVELGot 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!",}