发送推送消息

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。

  1. 在 Unity 编辑器中,选择 Edit(编辑)> Project Settings(项目设置)> Services(服务)

  2. 关联您的项目。
    如果项目没有 Unity Project ID:

    1. 选择 Create a Unity Project ID(创建 Unity Project ID)> Organizations(组织),然后从下拉选单中选择一个组织。
    2. 选择 Create project ID(创建 Project ID)


    如果已有 Unity Project ID:

    1. 选择 Use an existing Unity project ID(使用现有 Unity Project ID)
    2. 从下拉选单中选择组织和项目。
    3. 选择 Link project ID(关联 Project ID)

此时将显示您的 Unity Project ID,并将项目关联到 Unity 服务。此外,还可以使用 UnityEditor.CloudProjectSettings.projectId 参数在 Unity 编辑器脚本中访问您的 Project ID。

SDK 安装

安装适用于 Unity 编辑器的最新 Cloud Code 包:

  1. 在 Unity 编辑器中,打开 Window(窗口)> Package Manager(包管理器)
  2. 在 Package Manager(包管理器)中,选择 **Unity Registry(Unity 注册表)**列表视图。
  3. 搜索 com.unity.services.cloudcode 或在列表中找到 Cloud Code 包。
  4. 选择该包,然后单击 Install(安装)

注意:您可以使用 Cloud Code SDK 版本 2.4.0+ 订阅消息。

注意:要熟悉 Unity Package Manager(包管理器)界面,请参阅 Package Manager(包管理器)窗口文档。

SDK 设置

开始使用 Cloud Code SDK:

  1. 确保通过 Cloud Code 服务后台页面启用该服务。
  2. 确保 Cloud Code SDK 和 Authentication SDK 均已安装。
  3. 在 Unity 编辑器中选择 Edit(编辑)> Project Settings(项目设置)> **Services(服务)**登录到您的云项目。
  4. 在 Unity 编辑器中创建新的 C# Monobehaviour 脚本。请参阅 Unity 手册中的创建和使用脚本
  5. 在脚本中,使用 await UnityServices.InitializeAsync() 初始化 Core SDK。
  6. 在脚本中,初始化 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);
        }
	}
}

向玩家发送消息

要向玩家发送消息,请从模块中调用 SendPlayerMessageSendProjectMessage 函数。

要了解如何运行模块,请参阅运行模块

从 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 获取数据会更有效或更经济时,便可以使用这种方法。