发送推送消息
Cloud Code C# 模块允许您通过 WebSocket 将消息推送到客户端。本页将概述此功能,并介绍如何在 Cloud Code 模块和 Cloud Code SDK 中使用此功能。
注意:推送消息和推送通知在游戏中有不同的用途。推送消息定向投放到游戏中参与度较高的活跃玩家,而推送通知是当游戏处于非活动状态或在后台运行时推送到设备。
要发送推送消息,您需要调用模块终端。您可以从 Unity 编辑器中订阅推送消息。
用例和优点
推送消息可以有多种用途,例如:
用途 | 示例 | 优点 |
---|---|---|
将消息从服务器实时推送到客户端,并增强游戏的互动性。 | 您可以告知玩家有关游戏活动、更新或异步多人游戏(例如,竞技卡牌游戏)的信息。 | 实时交互 |
通过直接向客户端推送更新和通知,让用户及时了解游戏中的最新活动、变更或行动。 | 您可以在有新数据可用时立即通知用户,这样您就无需手动刷新或检查更新。这种功能对于需要频繁更新的游戏(例如实时战略游戏)特别有用。 | 用户体验 |
使用 WebSocket 推送消息,比传统的轮询技术效率更高。 | 您的客户端可以等待服务器在有新数据可用时发送这些数据,而不是不断要求服务器提供新数据。这样可以减少不必要的网络流量,并可以降低延迟。 | 提高网络使用效率 |
利用推送模型的可扩展性来支持拥有大量用户的游戏。 | 您可以在 Cloud Code 中使用推送消息一次性向所有已连接的客户端发送更新,从而降低拥有大量玩家的多人游戏的运营成本和请求量。 | 可扩展性和成本 |
使用事件驱动模型来自定义游戏对不同类型的消息的响应。 | 您可以根据收到的消息的 MessageType 属性触发不同的游戏操作。 | 可自定义 |
作为 Unity 生态系统的一部分,Cloud Code 可以与其他 Unity 服务无缝结合使用。 | 您可以使用 Unity 的 Authentication 服务处理玩家身份验证,并在 Unity 游戏引擎中处理消息。 | 无缝集成 |
创建模块
以下代码示例演示了包含两个方法的模块的基本结构:
SendPlayerMessage
:向已连接的特定玩家发送一条消息。SendProjectMessage
:向项目中所有已连接的玩家广播一条消息。
Unity.Services.CloudCode.Apis
包提供了 PushClient
实例作为用于发送推送消息的接口。
C#
using Microsoft.Extensions.DependencyInjection;
using Unity.Services.CloudCode.Core;
using Unity.Services.CloudCode.Apis;
namespace PushExample
{
public class PushExample
{
[CloudCodeFunction("SendPlayerMessage")]
public async Task<string> SendPlayerMessage(IExecutionContext context, PushClient pushClient, string message, string messageType, string playerId)
{
var response = await pushClient.SendPlayerMessageAsync(context, message, messageType, playerId);
return "Player message sent";
}
[CloudCodeFunction("SendProjectMessage")]
public async Task<string> SendProjectMessage(IExecutionContext context, PushClient pushClient, string message, string messageType)
{
var response = await pushClient.SendProjectMessageAsync(context, message, messageType);
return "Project message sent";
}
}
public class ModuleConfig : ICloudCodeSetup
{
public void Setup(ICloudCodeConfig config)
{
config.Dependencies.AddSingleton(PushClient.Create());
}
}
}
要了解如何部署模块,请参阅部署 Hello World 页面。
设置 Unity 编辑器
Cloud Code SDK 提供了一个用于订阅消息的接口。您可以订阅特定玩家或整个项目的消息。
要在 Unity 编辑器中使用 Cloud Code,必须先安装 Cloud Code SDK,并将 Unity Gaming Services(Unity 游戏服务)项目关联到 Unity 编辑器。
关联项目
将 Unity Gaming Services(Unity 游戏服务)项目与 Unity 编辑器关联。您可以在 Unity Dashboard(Unity 后台)中找到您的 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)。
此时将显示您的 Unity Project ID,并将项目关联到 Unity 服务。此外,还可以使用 UnityEditor.CloudProjectSettings.projectId
参数在 Unity 编辑器脚本中访问您的 Project ID。
SDK 安装
安装适用于 Unity 编辑器的最新 Cloud Code 包:
- 在 Unity 编辑器中,打开 Window(窗口)> Package Manager(包管理器)。
- 在 Package Manager(包管理器)中,选择 **Unity Registry(Unity 注册表)**列表视图。
- 搜索
com.unity.services.cloudcode
或在列表中找到 Cloud Code 包。 - 选择该包,然后单击 Install(安装)。
注意:您可以使用 Cloud Code SDK 版本 2.4.0+ 订阅消息。
注意:要熟悉 Unity Package Manager(包管理器)界面,请参阅 Package Manager(包管理器)窗口文档。
SDK 设置
开始使用 Cloud Code SDK:
- 确保通过 Cloud Code 服务后台页面启用该服务。
- 确保 Cloud Code SDK 和 Authentication SDK 均已安装。
- 在 Unity 编辑器中选择 Edit(编辑)> Project Settings(项目设置)> **Services(服务)**登录到您的云项目。
- 在 Unity 编辑器中创建新的 C# Monobehaviour 脚本。请参阅 Unity 手册中的创建和使用脚本。
- 在脚本中,使用 await
UnityServices.InitializeAsync()
初始化 Core SDK。 - 在脚本中,初始化 Authentication SDK。
注意:玩家必须拥有有效的玩家 ID 和访问令牌才能访问 Cloud Code 服务。在使用任何 Cloud Code API 之前,您必须使用 Authentication SDK 对玩家进行身份验证。为此,您可以使用以下代码片段进行匿名身份验证,或查看身份验证文档,了解更多详细信息和其他登录方法。
C#
await AuthenticationService.Instance.SignInAnonymouslyAsync();
订阅消息
您可以订阅特定玩家或整个项目的消息。您可以使用以下代码片段作为 Unity 项目的 MonoBehaviour
脚本参考指南。
该脚本以匿名玩家的身份进行身份验证,订阅特定于玩家和特定于项目的消息,并处理各种类型的事件:
C#
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();
await SubscribeToProjectMessages();
}
// 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);
}
// This method creates a subscription to project messages and logs out the messages received,
// the state changes of the connection, when the player is kicked and when an error occurs.
Task SubscribeToProjectMessages()
{
var callbacks = new SubscriptionEventCallbacks();
callbacks.MessageReceived += @event =>
{
Debug.Log(DateTime.Now.ToString("yyyy-MM-dd'T'HH:mm:ss.fffK"));
Debug.Log($"Got project subscription Message: {JsonConvert.SerializeObject(@event, Formatting.Indented)}");
};
callbacks.ConnectionStateChanged += @event =>
{
Debug.Log($"Got project subscription ConnectionStateChanged: {JsonConvert.SerializeObject(@event, Formatting.Indented)}");
};
callbacks.Kicked += () =>
{
Debug.Log($"Got project subscription Kicked");
};
callbacks.Error += @event =>
{
Debug.Log($"Got project subscription Error: {JsonConvert.SerializeObject(@event, Formatting.Indented)}");
};
return CloudCodeService.Instance.SubscribeToProjectMessagesAsync(callbacks);
}
}
}
向玩家发送消息
要向玩家发送消息,请从模块中调用 SendPlayerMessage
或 SendProjectMessage
函数。
要了解如何运行模块,请参阅运行模块。
从 Unity Runtime 运行
您可以通过 CloudCodeService
实例的 CallModuleEndpointAsync
方法向其他玩家发送消息。您需要使用模块名称和函数名称作为其前两个参数,并使用包含必要参数的字典作为第三个参数。
例如,要发送玩家消息,您可以调用:
var sendPlayerMessageResult = await CloudCodeService.Instance.CallModuleEndpointAsync<string>("PushExample", "SendPlayerMessage",
new Dictionary<string, object> {{"message", "hello with a player message from PushExample!"}, {"messageType", "testType"}, {"playerId", "<other-unity-player-ID>"}});
注意:对于此用例,您可以创建访问控制策略来限制玩家对终端的访问。例如,您可以确保玩家无法调用 SendProjectMessage
模块函数来向游戏中的所有其他玩家发送项目消息。
事件
特定于玩家的订阅和特定于项目的订阅都有四个事件处理程序:
MessageReceived
:当玩家收到新消息时触发。ConnectionStateChanged
:当连接状态改变时触发。Kicked
:当服务器强制取消订阅玩家的消息时触发。这不会关闭 WebSocket 连接,也不会阻止游戏客户端再次订阅消息。Error
:当连接处理发生错误或玩家接收消息发生错误时触发。
消息信封
IMessageReceivedEvent
作为一个接口,表示玩家从推送服务接收的消息。当 Cloud Code 通过 WebSocket 连接发送消息时,会触发该事件。
请参阅下表以了解 IMessageReceivedEvent
接口的有效负载:
属性 | 描述 | 示例 |
---|---|---|
SpecVersion | 收到消息的信封的规范版本。使用此属性来确保客户端可以正确处理消息。 | 1.0 |
Id | 消息的唯一标识符。使用此属性来跟踪或记录消息。 | 4f88f657-27da-4b1d-a013-9033dbc7b48b |
Source | 消息的信封的来源。此属性指示消息的来源,可用于调试或路由消息。该来源始终是 Cloud Code 域。 | https://cloud-code.service.api.unity.com |
Type | 消息的信封类型。此属性指示消息包含的数据类型,并帮助客户端确定处理方式。该值始终是 Cloud Code 消息类型。 | com.unity.services.cloud-code.push.v1 |
Time | 创建消息的日期和时间。您可以使用此属性来记录消息或计算延迟。 | 2023-09-19T10:26:40.436878688Z |
ProjectId | 与消息关联的项目的 ID。 | b6670776-9fd3-4d66-8bf4-63fb1112dc95 |
EnvironmentId | 消息所适用的环境的 ID。您可以使用此属性来区分不同的环境,例如开发、暂存和生产环境。 | a4bc2571-d1e7-4507-9cc9-80b687d48d8f |
CorrelationId | 一个可用于跟踪一系列相关消息的标识符。例如,如果多条消息形成一个对话或工作流程,这些消息可能会共享一个相关性 ID。 | afbd7c6e-e999-4ca2-86fc-3c908ba83bf2 |
Message | 从 Cloud Code 发送到玩家的实际消息内容。 | "hello world!" |
MessageType | 玩家收到的消息类型。此属性与 Type 类似,但取决于消息内容,而不是信封。 | "Information" |
网络带宽使用量和成本注意事项
使用 Cloud Code WebSocket 功能将消息推送到客户端时,需要特别注意网络带宽使用量和相关成本。
出口流量成本
从模块发送到客户端的每条消息都会占用网络带宽,这会影响模块的出站数据总量。Cloud Code 会将通过 WebSocket 连接推送消息的相关网络带宽使用量计入到 Cloud Code 出口流量成本中。
在设计应用程序并决定发送消息的时间和频率时,请务必牢记这一点。过多或不必要的大型消息可能会导致更高的出口流量成本。
如需详细了解 Cloud Code 定价,请参阅成本页面。
消息大小限制
Cloud Code 将通过 WebSocket 连接发送的消息大小限制为 10 KB。这意味着您需要管理发送的数据的大小,尤其是对于更复杂或数据密集型的应用程序。
您可以使用以下方法来确保让玩家了解最新情况,并保持较低的成本和网络带宽使用量:
发送数据的差异
如果需要传送大量数据或游戏状态发生重大变化,您可以发送数据的差异,而不是整个有效负载。差异是指应用于现有状态的一组更改,通常比完整状态数据小得多。
提示发出 HTTP 请求来获取数据
您可以使用 WebSocket 消息作为微移机制来通知客户端有新数据可用,并提示客户端发出 HTTP 请求以获取完整数据集。当完整数据集很大且只需要不频繁的更新时,或者当通过 HTTP 获取数据会更有效或更经济时,便可以使用这种方法。