抖音开放平台Logo
开发者文档
控制台

云适配能力
收藏
我的收藏

云适配能力是一组独立的工具类集合,用于帮助开发者适配云启动环境。​

API清单​

API 入口​
接入API​
返回 或 回调​
功能​
必须接入​
建议​
云游戏适配:​
ILiveCloudGameAPI
云启动云游戏​
(接口的实例通过 LiveOpenSdk.CloudGameApi 属性获取)​
IsCloudGame()
bool​
是否是云启动​
×否​
不需要做任何手动执行。平台上发布exe玩法包版本,已自动支持云启动、自动适配。​
仅用于可针对云启动做差异实现。​
IsStartFromMobile()
bool​
是否是从手机端启动​
×否​
TryInitFullScreen()
void
全屏,自动适配云游戏
×否
平台已支持云启动、自动适配。​
最新版本已不需要手动调用。​
CloudGameInput
兼容适配云游戏输入。 对齐PC端Input风格​
IsTouchMode
bool​
否处于触摸模式​
可选​
Input.GetMouseButtonDown
Input.GetMouseButtonUp
Input.mousePosition
bool​
bool​
Vector3​
兼容支持云游戏的:​
    手指触摸点击,适配到Mouse点击​
详见Sample目录中 Camera3DObjectClick.cs - Sample演示3D物体点击
    单指拖拽,适配到Mouse左键拖拽​
*CameraDragMove.cs - Sample演示镜头操作:拖拽移动​
可选​
替换开发者原有的Input后,开发者可以保持原Mouse输入代码,无需另写Touch输入代码)​
Input.GetAxis("Mouse ScrollWheel")
Input.mouseScrollDelta
Input.mouseScrollDelta.y
float​
Vector2​
float​
兼容支持云游戏的:​
    双指缩放,适配到PC滚轮​
*CameraZoomInOut.cs - Sample演示镜头操作:缩放​
可选​
同上​
Input.touches
Input.GetFingerTouch
Touch[]​
Touch​
兼容了手指触摸信息​
可选​
仅当"IsTouchMode"为true、表示是触摸模式时有有效返回​
CloudGameEventSystem
兼容适配云游戏EventSystem​
EventSystem.current
CloudGameEventSystem​
兼容了current EventSystem
可选​
IsPointerOverGameObject()
bool​
是否点击在UI上​
可选​
通常配合Input的点击、拖拽,判断输入信息一起使用​

云启动云游戏​

提示:​
    不需要做任何手动执行。平台上发布 exe 玩法包版本,已自动支持云启动、自动适配。​
    仅用于可针对云启动做差异实现。​
相关接口、仅用于可针对云启动做差异实现:ILiveCloudGameAPI (Runtime/API/ILiveCloudGameAPI.cs)​
/// <summary> /// 云启动云游戏API /// </summary> /// <remarks>会自动读取解析云启动参数。参考 https://developer.open-douyin.com/docs/resource/zh-CN/interaction/jierushuoming/pingtaijichu/cloud#0bf5266e</remarks> public interface ILiveCloudGameAPI { /// <summary> /// 是否是云启动。 /// </summary> /// <remarks>会读取云启动参数,参考 https://developer.open-douyin.com/docs/resource/zh-CN/interaction/jierushuoming/pingtaijichu/cloud#0bf5266e</remarks> bool IsCloudGame(); /// <summary> /// 是否是从手机端启动(手机抖音开播小玩法)。如果是PC伴侣开播,返回`false` /// </summary> /// <remarks>会读取云启动参数,参考 https://developer.open-douyin.com/docs/resource/zh-CN/interaction/jierushuoming/pingtaijichu/cloud#0bf5266e</remarks> bool IsStartFromMobile(); /// <summary> /// 尝试初始化全屏,自动适配云游戏设备的分辨率。 如果不是云启动云开播,不会产生影响。 /// </summary> void TryInitFullScreen(); }

兼容适配云游戏输入​

    按上文“接入方式”,替换开发者原有的Input后,开发者可以保持原Mouse输入代码,无需另写Touch输入代码。​
    实现以下sample功能。​

接入方式​

    接入方式1:在使用到Input的相关代码顶部,添加:​
using Input = Douyin.LivePlay.SDK.CloudGameInput; using EventSystem = Douyin.LivePlay.SDK.CloudGameEventSystem;
    接入方式2:使用到 UnityEngine.Input 的相关代码的Input.xxxEventSystem,手动替换为CloudGameInput.xxxCloudGameEventSystem
1. Input 把: if (Input.GetMouseButtonDown(0)) =>替换为: if (CloudGameInput.GetMouseButtonDown(0)) 2. EventSystem 把: EventSystem.current; EventSystem.current.IsPointerOverGameObject() =>替换为: CloudGameEventSystem.current; CloudGameEventSystem.current.IsPointerOverGameObject()

示例Sample代码

参见:​
    com.bytedance.liveopensdk/Samples/SampleInputControl/Camera3DObjectClick.cs - Sample演示3D物体点击
    com.bytedance.liveopensdk/Samples/SampleInputControl/CameraDragMove.cs - Sample演示镜头操作:拖拽移动
    com.bytedance.liveopensdk/Samples/SampleInputControl/CameraZoomInOut.cs - Sample演示镜头操作:缩放
💡注:这些Sample中的MonoBehaviour,都可直接用于挂载添加到你自己工程中的GameObject上​

手指点击适配​

    💡手指触摸点击,适配到Mouse点击​
详见Sample目录中 Camera3DObjectClick.cs - Sample演示3D物体点击
public class Camera3DObjectClick : MonoBehaviour; private void UpdateMouseButton() { // Check for button down if (Input.GetMouseButtonDown(0)) { // Skip if it is on GUI var eventSystem = EventSystem.current; if (eventSystem != null && eventSystem.IsPointerOverGameObject()) { ShowToast("点击了: UI"); return; } _isClicked = true; _clickedObject = GetClickedObject(Camera); var go = _clickedObject; if (go != null) ShowToast($"点击到了: {go.name}"); else ShowToast("点击了: 场景"); } // Check for button up if (_isClicked && Input.GetMouseButtonUp(0)) { _isClicked = false; var go = _clickedObject; if (go != null) ShowToast($"点击松开了: {go.name}"); else ShowToast("松开了: 场景"); } }

拖拽移动适配​

    💡单指拖拽,适配到Mouse左键拖拽​
详见Sample目录中 CameraDragMove.cs - Sample演示镜头操作:拖拽移动​
/// <summary> /// Sample演示镜头操作:拖拽移动 /// </summary> public class CameraDragMove : MonoBehaviour; void Update() { // Check for button down if (Input.GetMouseButtonDown(0)) { // Skip if it is on GUI var eventSystem = EventSystem.current; if (eventSystem != null && eventSystem.IsPointerOverGameObject()) { return; } var mousePosition = Input.mousePosition; if (IsPositionZero(mousePosition)) // 部分设备会在点击开始或结束一刻、偶现坐标0,0异常信息,需要排除 { Debug.Log("拖拽 Down 排除: 坐标0,0异常信息"); return; } _isDragging = true; _dragFromPosition = mousePosition; Debug.Log("拖拽 Down 开始"); } // Deactivate dragging when button up if (_isDragging && Input.GetMouseButtonUp(0)) { _isDragging = false; if (_isMoved) { _isMoved = false; ShowToast("拖拽移动结束"); } else { ShowToast("拖拽结束: 移动距离不足"); } } var targetTransform = CameraTransform; if (targetTransform == null) return; // Move the camera while the left mouse button is held down var held = Input.GetMouseButton(0); if (_isDragging && held) { var mousePosition = Input.mousePosition; if (IsPositionZero(mousePosition)) // 部分设备会在点击开始或结束一刻、偶现坐标0,0异常信息,需要排除 { Debug.Log("拖拽 held 排除: 坐标0,0异常信息"); return; } Vector3 screenDelta = mousePosition - _dragFromPosition; var delta = screenDelta.magnitude; var threshold = MoveDeltaThreshold; if (delta < threshold) return; if (!_isMoved) { threshold = MoveStartThreshold; if (delta < threshold) return; _isMoved = true; ShowToast($"拖拽开始: from {{ {_dragFromPosition.x:F1}, {_dragFromPosition.y:F1} }} (move: {delta:F2})"); } // apply transform position var speed = CameraSpeedFactor * _screenToCameraInternalFactor; speed = Mathf.Clamp(speed, 0.0001f, 100f); var positionOffset = new Vector3( -screenDelta.x * speed, 0, -screenDelta.y * speed ); targetTransform.position += positionOffset; _dragFromPosition = mousePosition; ShowToast($"拖拽移动了: {{ {screenDelta.x:F1}, {screenDelta.y:F1} }} (move: {delta:F2})"); } }

双指缩放适配​

    💡双指缩放,适配到PC滚轮​
详见Sample目录中 CameraZoomInOut.cs - Sample演示镜头操作:缩放​
/// <summary> /// Sample演示镜头操作:缩放 /// </summary> public class CameraZoomInOut : MonoBehaviour; public float GetMouseScrollDelta() { if (IsMouseScrollAxisMode) return Input.GetAxis("Mouse ScrollWheel") * _axisToScrollInternalFactor; else return Input.mouseScrollDelta.y; } void Update() { var scrollValueInput = GetMouseScrollDelta(); if (Mathf.Abs(scrollValueInput) > _scrollStepMaxValue) scrollValueInput = Mathf.Clamp(scrollValueInput, -_scrollStepMaxValue, _scrollStepMaxValue); _scrollValueAccumulate += scrollValueInput; // avoid problem if the wheel input values are frequent but very small LogDebugTouchInfo(); LogDebugScrollInfo(); if (IsFloatEqual(_scrollValueAccumulate, 0)) return; var scrollValue = _scrollValueAccumulate; // reset accumulated _scrollValueAccumulate = 0; // Skip if it is on GUI var eventSystem = EventSystem.current; if (eventSystem != null && eventSystem.IsPointerOverGameObject()) return; var targetTransform = CameraTransform; if (targetTransform == null) return; // Zoom the camera based on mouse scroll input var speed = ZoomSpeedFactor * _internalFactor; Vector3 offsetPosition; switch (zoomType) { case ZoomType.AxisY: offsetPosition = Vector3.down * scrollValue * speed; break; case ZoomType.AxisZ: offsetPosition = Vector3.forward * scrollValue * speed; break; default: case ZoomType.Forward: offsetPosition = targetTransform.forward * scrollValue * speed; break; } var prevPosition = targetTransform.position; var position = prevPosition + offsetPosition; if (position.y < ZoomCameraMinY) { var y0 = prevPosition.y; var y1 = position.y; var yt = ZoomCameraMinY; var ratio = Mathf.Abs(yt - y0) / Mathf.Abs(y1 - y0); position = Vector3.Lerp(prevPosition, position, ratio); if (y0 < yt) { // reset back ratio = (yt - y0) / (y1 - y0); position = Vector3.LerpUnclamped(prevPosition, position, ratio); } } targetTransform.position = position; ShowToast($"缩放滚动了: {scrollValue:F3}"); }