腾讯2022数字生态大会在深圳宝安的国际会展中心举行,为了让更多云端观众也能参与,大会特别开设了“全真互联未来会场”,支持海量用户化身“阿凡达” 登录虚拟的会展空间,像体验3D大作一样参会,并与其他用户、AI 数智人实时互动。两天会期内,总计有13000多人进入了未来会场,观众累计体验时长超20万分钟。手机打开微信小程序搜索“腾讯全球数字生态大会-未来会场”,即可体验完整功能!








未来会场基于 Unreal Engine打造,场景精细、功能丰富,但用户无需下载,无需高端的手机配置,在小程序上即可享受高清、流畅的虚拟参会体验,这是通过接入应用云渲染产品来实现的。本篇文档将基于该案例,为您剖析如何接入应用云渲染产品,如何从零开始搭建这样一个全真互联未来会场小程序,整体流程可参考下图:

接入前:应用开发
首先,您需要打造一个可在 Windows 环境下稳定运行的应用程序,在应用层面开发实现必要的功能。
例如,全真互联未来会场应用程序内实现了以下功能:
支持通过键盘 WASD/上下左右来操控人物移动,鼠标左键拖动操控视角:可通过引入虚拟摇杆插件适配手机端操作(详细请参见 步骤2-前端-基础用法)。
支持多人在线互动:建立一个 服务器 主持多人会话,所有其他用户使用 部署至应用云渲染的客户端连接到该服务器。
多人视频、语音、文字聊天功能。
嵌入图片/视频/直播流、实现虚拟形象表情动作、场景内放烟花、灯光秀等更多功能和玩法。
说明:
以上功能不是接入应用云渲染的必要条件,您可以按需实现,应用云渲染对您应用内功能的具体实现没有特殊要求,您也无需在 Unity 或 Unreal Engine 中进行特殊配置。不过为了实现更好的终端用户体验,在技术接入阶段(步骤2)您可以对应用做些针对性的调整,如将应用设置为无边框模式并开启自适应桌面分辨率(具体请参见步骤2-前端-高级功能)。
步骤1:控制台部署应用并测试效果

2. 新建项目并关联上传的应用程序(参考新建项目)。
3. 在项目下购买并发 (参考 购买并发包)。
4. 进行效果测试。
步骤2:下载接入 Demo 搭建业务前端和后台
完成效果测试后,为了实现云渲染服务管理、更好的前端操作体验、小程序适配等,您还需要搭建自己的客户端程序以及后台服务,接入应用云渲染提供的各终端 SDK和后端 API ,我们提供接入 Demo帮助您快速实现业务上线。


前端部分
基础概念
基础用法 - 页面准备工作
在页面中引入初始化脚本(JS SDK 下载)。
<script src="path/to/sdk" charset="utf-8"></script>
或代码中 import。
import TCGSDK from 'path-to-TCGSDK';
基础用法 - 编写页面代码
1. 初始化 TCGSDK。
TCGSDK.init({...initOptions})
2. 在 onInitSuccess 回调中启动项目,获取 ServerSession。
onInitSuccess: async () => {await StartProject();}
TCGSDK.start(ServerSession);
4. 启动成功后在移动端,模拟键鼠操作。
onTouchEvent: async (res) => {// res type 为 array,array 长度代表当前手机屏幕触摸的手指数// console.log('onTouchEvent', res);// 针对单指触控操作if (res.length === 1) {const { id, type, pageX, pageY } = res.pop();// console.log('onTouchEvent', id, type, pageX, pageY);// 模拟将鼠标移到触摸点TCGSDK.mouseMove(id, type, pageX, pageY);// 判断 touchstart 发送鼠标左键按下if (type === 'touchstart') {TCGSDK.sendRawEvent({ type: 'mouseleft', down: true });}// 判断 touchend 或 touchcancel 发送鼠标左键抬起if (type === 'touchend' || type === 'touchcancel') {TCGSDK.sendRawEvent({ type: 'mouseleft', down: false });}}}
5.
引入摇杆插件,摇杆插件通常对应键盘 WASD/上下左右 按键
。5.1 添加以下代码引入插件。
<script type="text/javascript" src="path/to/joystick.js"></script>
5.2 在 onConnectSuccess 回调函数中创建摇杆。
// 添加摇杆 plugin-point 为需要挂载插件的 element 的 IDconst j = new CloudGamingPlugin.joystick({zone: document.querySelector('#plugin-point'),});

完整代码如下:
注意替换 TCGSDK,Joystick plugin 的路径
<!doctype html><html><head><meta charset="utf-8" /><meta name="apple-mobile-web-app-capable" content="yes" /><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=0" /><title>腾讯云-云渲染-应用云渲染-从零实现腾讯云生态大会云渲染小程序</title><style>* {padding: 0;margin: 0;}html,body {width: 100%;height: 100%;overflow: hidden;font-family: '黑体', 'Microsoft YaHei', 'Arial', 'sans-serif';}#demo-container {width: 100%;height: 100%;}</style></head><body><div id="demo-container"><div id="mount-point"></div></div><script type="text/javascript" src="path/to/tcg-sdk"></script><script type="text/javascript" src="path/to/joystick.js"></script><script type="text/javascript" src="https://cdn.bootcdn.net/ajax/libs/axios/0.26.1/axios.min.js"></script><script>// 对于应用云渲染,后台服务接口 StartProject 其实就是后台串行调用了云API的 ApplyConcurrent + CreateSession// 申请并发(ApplyConcurrent) https://cloud.tencent.com/document/api/1547/72827// 创建会话(CreateSession) https://cloud.tencent.com/document/api/1547/72826const StartProject = async () => {const url = 'https://xxxx/StartProject'; // 后台端实现可以参考后台 demo 方案// 其他选填参数可以参考 ApplyConcurrent 接口文档const { data } = await axios.post(url, {ProjectId: 'project-id', // 项目IdUserId: 'user-id', // 用户Id,不同用户应该采用不同 UserId,同一UserId,会存在互踢现象ClientSession: TCGSDK.getClientSession(),});console.log('%c StartProject res', 'color: blue; font-size: 14px', data);const { Code, SessionDescribe: { ServerSession } } = data;if (Code === 0) {TCGSDK.start(ServerSession);} else {// 请求异常处理}}// 云渲染接入功能流程说明可以参考 https://ex.cloud-gaming.myqcloud.com/cloud_gaming_web/docs/index.htmlTCGSDK.init({appid: 1234567,mount: 'mount-point',debugSetting: {showLog: true,},// 连接成功回调onConnectSuccess: async (res) => {console.log('onConnectSuccess', res);},// 网络中断/被踢触发此回调onDisconnect: (res) => {console.log('onDisconnect', res);// 添加摇杆 plugin-point 为需要挂载插件的 element 的 IDconst j = new CloudGamingPlugin.joystick({zone: document.querySelector('#plugin-point'),});},onWebrtcStatusChange: (res) => {console.log('onWebrtcStatusChange', res);},// 移动端触摸,模拟发送 PC 上指令onTouchEvent: async (res) => {// res type 为 array,array 长度代表当前手机屏幕触摸的手指数// console.log('onTouchEvent', res);// 针对单指触控操作if (res.length === 1) {const { id, type, pageX, pageY } = res.pop();// console.log('onTouchEvent', id, type, pageX, pageY);// 模拟将鼠标移到触摸点TCGSDK.mouseMove(id, type, pageX, pageY);// 判断 touchstart 发送鼠标左键按下if (type === 'touchstart') {TCGSDK.sendRawEvent({ type: 'mouseleft', down: true });}// 判断 touchend 或 touchcancel 发送鼠标左键抬起if (type === 'touchend' || type === 'touchcancel') {TCGSDK.sendRawEvent({ type: 'mouseleft', down: false });}}},onInitSuccess: async (res) => {console.log('%c onInitSuccess', 'color: red', res);await StartProject();}});</script></body></html>
高级功能 - 多点触控
移动端多点触控可以分为两种形式:
云端应用支持多点触控,支持触摸事件,可直接设置 init 参数
clientInteractMode: 'touch'
,SDK 回自动发送 touch 相关指令致应用。云端应用不支持多点触控,仅支持鼠标键盘,可根据 onTouchEvent 回调,拿到对应触摸点坐标,发送 键盘/鼠标 指令完成业务逻辑。
高级功能 - 移动端自适应屏幕分辨率
高级功能 - 屏幕旋转
对于应用云渲染场景,由于云端总是推横屏流(宽大于高),所以在移动端手机竖屏显示时候可设置屏幕旋转,则将横屏流旋转为竖屏显示。屏幕旋转也可以搭配摇杆使用,摇杆插件已做兼容。
提供以下两种方法:
(推荐使用)TCGSDK init 参数中设置 autoRotateContainer: boolean,自动旋转屏幕。业务方不需要任何操作,所有逻辑 TCGSDK 接管。
调用 TCGSDK.setVideoOrientation 方法,旋转屏幕。
高级功能 - 数据通道
如果期望实现 Web 页面与云上应用数据互传可以使用数据通道功能,例如透传微信名和头像信息至云端应用。数据通道相关逻辑建议在 onConnectSuccess 回调中执行,调用 createCustomDataChannel 接口,发送数据类型支持 string 和二进制数据。详细实现流程及代码可以参考 技术接入-数据通道。

高级功能 - 排队功能
当用户在线数大于资源并发数量时,建议业务引入用户排队系统,提升用户体验。

后台部分
基础概念
基础用法 - 启动应用
1. 后台服务调用云渲染 API ApplyConcurrent() 锁定云渲染并发,收到成功回调后执行下一步。
// Depends on tencentcloud-sdk-nodejs version 4.0.3 or higherconst tencentcloud = require("tencentcloud-sdk-nodejs");const CarClient = tencentcloud.car.v20220110.Client;// 实例化一个认证对象,入参需要传入腾讯云账户secretId,secretKey,此处还需注意密钥对的保密// 密钥可前往https://console.cloud.tencent.com/cam/capi网站进行获取const clientConfig = {credential: {secretId: "SecretId",secretKey: "SecretKey",},region: "",profile: {httpProfile: {endpoint: "car.tencentcloudapi.com",},},};const client = new CarClient(clientConfig);const params = {"UserId": "user-id","UserIp": "user-ip","ProjectId": "project-id"};client.ApplyConcurrent(params).then((data) => {console.log(data);},(err) => {console.error("error", err);});
package mainimport ("fmt""github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common""github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/errors""github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile"car "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/car/v20220110")func main() {// 实例化一个认证对象,入参需要传入腾讯云账户secretId,secretKey,此处还需注意密钥对的保密// 密钥可前往https://console.cloud.tencent.com/cam/capi网站进行获取credential := common.NewCredential("SecretId","SecretKey",)// 实例化一个client选项,可选的,没有特殊需求可以跳过cpf := profile.NewClientProfile()cpf.HttpProfile.Endpoint = "car.tencentcloudapi.com"// 实例化要请求产品的client对象,clientProfile是可选的client, _ := car.NewClient(credential, "", cpf)// 实例化一个请求对象,每个接口都会对应一个request对象request := car.NewApplyConcurrentRequest()request.UserId = common.StringPtr("user-id")request.UserIp = common.StringPtr("user-ip")request.ProjectId = common.StringPtr("project-id")// 返回的resp是一个ApplyConcurrentResponse的实例,与请求对象对应response, err := client.ApplyConcurrent(request)if _, ok := err.(*errors.TencentCloudSDKError); ok {fmt.Printf("An API error has returned: %s", err)return}if err != nil {panic(err)}// 输出json格式的字符串回包fmt.Printf("%s", response.ToJsonString())}
2. 后台服务调用云渲染 API CreateSession() ,获取成功回调中的 ServerSession 返回给客户端。
// Depends on tencentcloud-sdk-nodejs version 4.0.3 or higherconst tencentcloud = require("tencentcloud-sdk-nodejs");const CarClient = tencentcloud.car.v20220110.Client;// 实例化一个认证对象,入参需要传入腾讯云账户secretId,secretKey,此处还需注意密钥对的保密// 密钥可前往https://console.cloud.tencent.com/cam/capi网站进行获取const clientConfig = {credential: {secretId: "SecretId",secretKey: "SecretKey",},region: "",profile: {httpProfile: {endpoint: "car.tencentcloudapi.com",},},};const client = new CarClient(clientConfig);const params = {"UserId": "user-id","UserIp": "user-ip","ClientSession": "client-session"};client.CreateSession(params).then((data) => {console.log(data);},(err) => {console.error("error", err);});
package mainimport ("fmt""github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common""github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/errors""github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile"car "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/car/v20220110")func main() {// 实例化一个认证对象,入参需要传入腾讯云账户secretId,secretKey,此处还需注意密钥对的保密// 密钥可前往https://console.cloud.tencent.com/cam/capi网站进行获取credential := common.NewCredential("SecretId","SecretKey",)// 实例化一个client选项,可选的,没有特殊需求可以跳过cpf := profile.NewClientProfile()cpf.HttpProfile.Endpoint = "car.tencentcloudapi.com"// 实例化要请求产品的client对象,clientProfile是可选的client, _ := car.NewClient(credential, "", cpf)// 实例化一个请求对象,每个接口都会对应一个request对象request := car.NewCreateSessionRequest()request.UserId = common.StringPtr("user-id")request.UserIp = common.StringPtr("user-ip")request.ClientSession = common.StringPtr("client-session")// 返回的resp是一个CreateSessionResponse的实例,与请求对象对应response, err := client.CreateSession(request)if _, ok := err.(*errors.TencentCloudSDKError); ok {fmt.Printf("An API error has returned: %s", err)return}if err != nil {panic(err)}// 输出json格式的字符串回包fmt.Printf("%s", response.ToJsonString())}
高级功能 - 排队功能
更多介绍
更多功能说明请查看 技术接入 文档 和 SDK 文档,如您有任何疑问或建议,或有特殊产品功能需求,请联系我们获得帮助。
并发包购买参考
对于类似全真互联未来会场的应用场景,一般在活动期间购买百-千路包天并发资源支持短期高并发用户需求,再购买数十路包月并发资源支持长期运营使用,即可满足业务需要,具体数量取决于实际业务需求。更多说明请参考 计费说明-根据业务场景选择最佳计费方式,如您有特殊计费需求,请联系我们。
体验小程序完整功能
除了接入应用云渲染产品,全真互联未来会场小程序还整合了腾讯云快直播、TRTC、IM、Avatar、数智人等产品和前沿技术,实现了虚拟形象、多人互动、直播、AI问答等多种玩法。手机微信搜索“腾讯全球数字生态大会-未来会场”小程序,即可体验完整功能,更多说明请参见走进未来——全真互联未来会场,今年的亮点都在这里!
说明:
建议您使用手机体验“腾讯全球数字生态大会-未来会场”小程序,效果更佳!