跳到主要内容

高级功能示例

Unity 云渲染提供了Unity游戏与客户端通信、自定义鉴权等高级功能,使用高级功能时需要在Unity游戏客户端引入依赖unity-cloudrendering-package,从而实现与JS、Android和IOS客户端的通信等功能。

unity-cloudrendering-package接入方式

unity-cloudrendering-package有如下接入方式:

方式说明使用限制
本地安装下载之后在Package Manager选择Add package from disk,选择下载的unity-cloudrendering-package进行安装仅支持Unity Editor 2021.3.12f1c1 之后的LTS版本
Unity Registry搜索并且安装unity-cloudrendering-package插件仅支持Unity Editor 2021.3.12f1c1 之后的LTS版本

通信

Unity云渲染JS SDK支持游戏客户端与游戏进行通信,以进行用户自定义的游戏内部控制。用户可以向游戏发送字符串或者接收游戏端发送的字符串。

Unity游戏

Unity游戏在嵌入unity-cloudrendering-package之后可以主动向前端发送消息:

// 接收消息
UGPMessage.Instance.RegisterReceiveMessageCallback("test", OnReceivedAckMessage);

private void OnReceivedAckMessage(string msgContent)
{
try
{
Debug.Log($"[Demo]: Received ack message: {msgContent}");
}
catch (Exception)
{
Debug.Log("[Demo] Failed to receive message.");
}
}

// 发送消息
UGPMessage.Instance.TrySendMessage("123", JsonUtility.ToJson(msg));

JS客户端

在游戏成功启动之后,客户端可以向游戏发送字符串。

  // 向Unity发送消息,注意,只有在GameStatusEvent.OnStartGameSuccess之后才能够调用此函数向Untiy发送消息
sendStringMessage = () => {
const { player } = this.state
if(player){
player.sendStringMessage('test', JSON.stringify({
player_name: 'xxx',
brand_id: "xxx"
}))
}
}

Unity注册接收消息函数时,mskKey同样为test才能收到消息。

客户端可以通过注册回调对收到的消息进行处理

// 游戏创建成功之后注册回调函数
player.onStringMessageReceived('test', this.onReceiveStringMsg)

// 收到Unity消息处理逻辑
onReceiveStringMsg = (msg: string) => {
console.log(msg)
}

其中onStringMessageReceived的第一个参数msgKey与Unity端的mskKey相同才能够成功收到回调消息。

自定义标签和查询

在某些业务场景中,您可能需要监控和获取游戏会话状态,并且需要筛选不同来源、不同分组的游戏会话分别进行管理,因此Unity云渲染提供了自定义标签的功能,以便于您实现客户端会话的管理。

SDK 传入自定义标签

首先,您可以根据具体业务条件,在初始化游戏的时候传入自定义的键值对,如:

// 需要在launchGame之前进行设置
clientInfo.customerTagsMap = new Map<string, string>()
clientInfo.customerTagsMap?.set("env", "dev")
clientInfo.customerTagsMap?.set("source", "chrome")
// launchGame

上面只是简单的静态示例,实际项目中您可以根据需求读取client的信息填入自定义标签中。

根据自定义标签查询游戏会话数量

Unity Cloud Rendering提供了OpenAPI,可以根据标签查询对应的游戏会话的数量。 调用OpenAPI需要先获取Unity STS Token,可以参考操作指南文档获取STS Token,只有正确携带了STS Token的请求才会被Unity云渲染平台接收和处理。

/api/count_game_session

接口地址:
URL: https://cloudrendering.unity.cn/api/count_game_session
Method: POST
Authorization: Unity STS
请求参数
参数名称是否必填示例值参数介绍详细信息
applicationId64d2056c846e6e159304a403应用ID,获取方式同SDK
tagKey"env"自定义标签键请填写在客户端传入的自定义标签的键
gameSessionStatus["started"]游戏会话状态列表,接口会返回在列表中的状态的游戏会话的数量可选值 ["started", "queueing", "retain", "stopped"],分别表示游戏运行中、排队中、保留中(用户断开但是保留等待重连),已停止
返回参数
参数名称示例值参数介绍详细信息
tagKey"env"同请求参数
countResult{ "dev": { "gameSessions": 3, "gameSessionsWithStatus": 1 }, "prod": { "gameSessions": 1, "gameSessionsWithStatus": 1 } }根据自定义标签键返回的游戏会话数量统计结果其中 gameSessions 为统计的游戏会话数量,gameSessionsWithStatus 为符合状态的游戏会话数量
CURL示例
# request
curl -X 'POST' \
'https://cloudrendering.unity.cn/api/count_game_session' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer [Your STS Token]' \
-d '{
"applicationId": "64d2056c846e6e1593xxxx",
"gameSessionStatus": [
"started",
"stopped"
],
"tagKey": "env"
}'

# response
{
"tagKey": "env",
"countResult": {
"dev": {
"gameSessions": 3,
"gameSessionsWithStatus": 1
},
"prod": {
"gameSessions": 1,
"gameSessionsWithStatus": 1
}
}
}

自定义鉴权

在某些业务场景中,可能需要确保所有的云端运行实例在启动前向业务侧进行权限校验。云渲染提供了实例运行前的权限校验功能。您只需要在应用编辑页面配置好业务服务端的鉴权API地址,并在初始化SDk的时候传入用于校验的token,云渲染会在应用生命周期的初始化阶段带入该token调用鉴权API进行验证。若返回200的状态码,则表示鉴权成功,可以继续启动应用。

设置鉴权API地址

在云渲染网页端的应用编辑页面,将业务侧鉴权API地址填入应用鉴权API Url一栏。若不填则表示不需要进行鉴权调用。

SDK初始化时传入token

参考API文档生命周期部分的 GamePlayer.Init 方法

API请求与响应格式

云渲染服务端在应用运行前会将token放入请求Body调用用户早前设置的API:

Authorization: Bearer <token>

收到响应后,通过状态码判断是否通过验证,当且仅当状态码为200时认为鉴权通过,将发起应用的云端运行。

音频采集(麦克风)

云渲染支持调用浏览器端麦克风采集音频,并发送音频数据到云端的应用。该功能可以帮助开发者实现诸如语音聊天,语音识别等高级功能。

唤起麦克风

在Unity端的脚本中调用如下API可以通知客户端(浏览器)唤起麦克风,一般需要用户在浏览器中确认授权

CloudStreaming.EnableMicRecording();

调用后即开始音频采集并发送至云端的Unity应用

关闭麦克风

在Unity端的脚本中调用如下API可以通知客户端(浏览器)关闭麦克风

CloudStreaming.DisableMicRecording();

调用后即停止音频采集

音频数据获取

在Unity端的脚本中调用如下API可以获取原始音频数据(PCM格式,单声道,采样率为48000Hz)

 var data = CloudStreaming.PeekRemoteAudioCapture();

一般推荐在Update()方法中获取音频数据,并存入AudioClip中,完整示例如下:

using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.Rendering;

public class CloudRenderingMicDemo : MonoBehaviour
{
public AudioSource audioSource;
private bool m_MicEnable = false;
private List<float> m_curFrameAudioData;

// 采样率为48000Hz
private int m_AudioSampleRate = 48000;
private AudioClip m_clip;

private void OnEnable()
{
// 创建临时缓冲区暂存音频数据,需要时一并写入AudioClip
m_curFrameAudioData = new List<float>();
}

private void OnDisable()
{
// 禁用麦克风
CloudStreaming.DisableMicRecording();
// 释放缓冲区
m_curFrameAudioData.Clear();
// 标记状态
m_MicEnable = false;
}

void Update()
{
// 通过事件打开或关闭麦克风(此处以按下S键为例)
if(Input.GetKeyDown(KeyCode.S))
{
if (m_MicEnable)
{
CloudStreaming.DisableMicRecording();

// 必要时将缓冲区中的数据写入AudioClip中,以便对音频数据进行播放或者其他操作
CreateClipAndPlay();
}
else
{
m_curFrameAudioData.Clear();
CloudStreaming.EnableMicRecording();
}
m_MicEnable = !m_MicEnable;
Debug.LogError($"m_MicEnable: {m_MicEnable}");
}

// 获取音频数据存入缓冲区
if(m_MicEnable)
{
var data = CloudStreaming.PeekRemoteAudioCapture();
m_curFrameAudioData.AddRange(data);
}
}

private void CreateClipAndPlay()
{
if (m_clip != null)
{
DestroyImmediate(m_clip);
}

if (m_curFrameAudioData.Count == 0)
{
Debug.LogError("no audio data !!!");
return;
}

// 创建AudioClip, 长度为缓冲区当前长度,单声道
m_clip = AudioClip.Create("test_audio_clip", m_curFrameAudioData.Count, 1, m_AudioSampleRate, false);

// 将缓冲区数据一并写入AudioClip
m_clip.SetData(m_curFrameAudioData.ToArray(), 0);

// 将clip绑定到AudioSource以便后续操作
audioSource.clip = m_clip;

// 此处以播放音频为例
audioSource.Play();

m_curFrameAudioData.Clear();
}
}

Unity 客户端虚拟键盘事件响应

在移动端设备上,为了支持游戏内输入。Unity云渲染SDK提供了虚拟键盘输入法,此输入法在大部分场景下可以正常工作,但是部分情况下,游戏可能需要在虚拟键盘出现或者关闭时执行某些操作。 因此,unity-cloudrendering-package提供了对应的事件响应以便游戏响应虚拟键盘出现和消息的事件执行对应的逻辑。

Unity游戏使用示例如下:

public class demo : MonoBehaviour
{
void Start()
{
// xxx
UgpEvent.Instance.RegisterKeyBoardEvent(OnKeyboardShow, OnKeyboardHide);
}

private void OnKeyboardShow()
{
Debug.Log("Keyboard show");
// do something when keyboard shown
}

private void OnKeyboardHide()
{
Debug.Log("Keyboard hide");
// do something when keyboard hidden
}
}