HOME> 意大利世界杯夺冠> 奇遇 Unity XR SDK 开发文档 - iQIYIVR/QIYU
{$vo.文章标题}
{$vo.文章标题}

奇遇 Unity XR SDK 开发文档 - iQIYIVR/QIYU

admin
8359

一、Unity XR SDK

1.1 简介

本文档介绍在Unity游戏开发引擎环境下,开发者使用奇遇 Unity XR SDK(以下简称SDK)制作运行在奇遇VR一体机设备上的VR应用和游戏。

1.2 主要特性

基于UnityXR Plug-in标准接口框架,提供VR应用开发包。

采用先进的由内而外的追踪系统,达到毫米级精度。

奇遇3手柄控制器为六自由度控制器,实现直观自然的手部运动仿真。

Singlepass、Foveation Rendering、Vulkan等高级渲染功能提高性能。

高质量3D音频,为数字音频工作站提供插件。

提供免费的DLC上传和下载服务,帮助开发者减少APK下载大小。

1.3 开发环境要求

软件要求

Unity Editor

必须使用unity2019.4.22f1以上版本

Android SDK

API Level 26(Android 8.0) 及以上

JDK

JDK 1.8.0及以上

硬件要求

奇遇3一体机

QIYU OS v1.6.1及以上

1.4 Unity Package 目录说明

SDK通过zip包格式提供,开发者导入后可看到如下目录:

Assets目录:SDK的模型,材质,shader等资源

Editor目录:SDK用编辑器工具

Rumtime目录:SDK相关运行时脚本

Samples目录:SDK相关Samples例子工程

package.json文件:SDK配置文件,导入SDK的入口

二、奇遇3 VR一体机

奇遇3是爱奇艺智能科技有限公司(简称:爱奇艺智能)研发的6自由度一体式VR设备,搭载高通XR2芯片,采用基于计算机视觉技术的Inside-out毫米级定位追踪方案,拥有一对6自由度定位追踪的手柄控制器。下表列举了奇遇3设备的基本参数:

屏幕

单眼分辨率2160 x 2160,刷新率 90HZ

芯片

高通骁龙 XR2

内存

8GB

存储

128GB

网络

WiFi 6

蓝牙

BT 5.1

声音

双麦克风录音,双扬声器

追踪摄像头

四个语言追踪摄像头

电池

5500mAh

接口

USB Type-C,3.5mm 耳机插口

定位追踪

头部和手部Inside-Out毫米级定位追踪

手部追踪范围垂直方向160°、水平方向160°

控制器

两个6自由度手柄控制器

视场角

95°

三、快速入门

了解如何导入SDK软件包,以及如何针对您的开发环境进行基本测试。

我们假设您已经了解了什么是虚拟现实及其使用的术语。 如果不是,请检查Unity XR词汇表。

强烈建议您在使用SDK之前,先阅读Unity XR文档,然后正确安装Unity Editor和ADB调试工具。

步骤1:

打开Unity Editor,新建工程

图3.1 创建工程

步骤2:

修改Platform为Android平台

图3.2 修改Platform

步骤3:

导入SDK

PackageManager选择加号->Add package from disk按钮加载上面解压目录的package.json文件,XR插件就会自动导入。

图3.3 导入SDK

步骤4:

导入后,点击“Yes”,启用Unity new input System,Unity Editor会自动重启。

图3.4 启用Unity new input System

步骤5:

导入以后会看到Qiyu XR Plugin;如果有需要,点击Import into Project导入Sample工程。

图3.5 导入Samples

步骤6:

新建场景,创建XRRig,XRRig提供的功能参见4.1UnityXR介绍。

图3.6 创建XR Rig

步骤7:

必须在ProjectSettings—>XRPlug-in Management里的勾选“Qiyu”选项

图3.7 开启Qiyu

步骤8:

设置推荐配置,可通过“Menu/Qiyu/Modify Player Settings”一键自动设置为推荐配置。

图3.8 常用菜单功能

配置项

推荐值

GraphicsAPIs

OpenGLES3

ApiCompatibilityLevel

.NET 4.x

minSdkVersion

AndroidApiLevel26

Scripting Backend

IL2CPP

Target Architectures

ARM64

Default Orientation

LandscapeLeft

vSyncCount

Every V Blank

表3.1 工程推荐配置

步骤9:

如果需要使用自定义AndroidManifast.xml文件,可以点击Qiyu->Tools->Create AndroidManifast按钮创建SDK需要的默认配置模板,在此基础上进行修改。不需要的时候可以点击Delete AndroidManifast按钮进行删除。

图3.9 创建AndroidManifast配置

步骤10:

打包,安装进一体机运行

四、功能介绍

4.1 UnityXR

奇遇UnityXR SDK基于UnityXR Plug-in Framework(https://docs.unity3d.com/Manual/XR.html)开发,目前支持以下UnityXR子系统,具体接口说明参见UnityXR说明文档:

Subsystem

Reference

XRDisplaySubsystem

https://docs.unity3d.com/Manual/xrsdk-display.html

XRInputSubsystem

https://docs.unity3d.com/Manual/xrsdk-input.html

XRNodeState

https://docs.unity3d.com/ScriptReference/XR.XRNodeState.html

XRSettings

https://docs.unity3d.com/ScriptReference/XR.XRSettings.html

4.2 XRRig

本指南介绍了UnityXR为开发者提供的统一XR Rig prefab及功能。

图4.1 XR Rig配置面板

4.2.1 Tracking Origin Mode

用于设置追踪原地的模式。

Device:以头显位置和方向作为参考进行追踪,Recenter会复原虚拟相机的位置

Floor:以头显检测到的地面为参考面进行追踪,Recenter不会改变虚拟相机的高度

注:对于多场景应用中,XRRig的使用注意,参见7.1 XRRig使用注意

4.3 QiyuManager

本指南介绍了奇遇为开发者提供的一些常用功能,如果需要,请将QiyuManager prefab拖进场景。

图4.2 QiyuManager 预制体

图4.3 QiyuManager 配置面板

4.3.1 Foveation Level

详细说明参见4.6.1注视点渲染

4.3.2 Eye Resolution Scale Factor

设置RenderTexture缩放系数,默认为1(推荐),即采用系统提供的尺寸,开发者可根据场景需要调整。如果小于1,画面清晰度会降低,但帧率会提升,功耗降低;如果大于1,画面清晰度会进一步提升,但是帧率会降低,功耗和内存会增加。建议最大值不要超过1.5。

4.3.3 使用3Dof模式

HMD 3Dof:MainCamera的Tracked Pose Driver组件的Tracking Type改为Rotation Only。

图4.4 头3Dof 模式

Controller 3Dof:调用接口Utils.SetTrackingPosition(false)。

4.4 输入

本指南描述了SDK支持的输入交互功能。

4.4.1 通用输入接口

UnityEngine.XR.InputDevices封装了所有的设备输入接口,目前包括手柄控制器的输入接口。开发者可查阅XR Interaction Toolkit教程(https://docs.unity3d.com/Packages/[email protected]/manual/index.html)接入输入功能。

4.4.2 奇遇3手柄控制器

如果开发者需要在场景中使用奇遇3手柄模型,可将QIYI3_Handle拖进XRcontroller指定Model Prefab位置。

图4.5 奇遇3手柄按键示意图

图4.6 使用奇遇3手柄模型

4.4.3 VR输入法键盘

奇遇 SDK中提供了VR输入法键盘,方便开发人员将虚拟键盘放置在应用程序中。

将VRInputField Prefab 拖动到UI中。

单击控件以弹出虚拟键盘。

可参考SGKeyboard.unity 示例场景。

图4.7 VR输入法键盘

4. 开发者可根据需要调节Controller参数,为了提升键盘操作的体验,推荐Device-based模式下,手柄按键阈值使用0.5。

图4.8 XR Controller属性面板

5. 设置左右手输入,如果只需要使用其中一个,可以将另外一个值NULL。

图4.9 输入法配置面板

6. 注意必须把ProjectSettings里的Active Input Handling设置为Both

图4.10 Both设置

4.5 声音

本指南介绍了在Unity中创建引人入胜的VR音频体验的开发资源。

4.5.1 Unity AudioSource

添加AudioSource组件,设置3D音效

开发者可在ProjectSettings-Audio中配置空间音频插件

4.5.2 Resonance Audio插件

Resonance Audio是一个多平台的空间音频SDK,可提供高保真度、强大的空间音频技术,对于VR游戏和视频的真实体验有很大的帮助。

插件下载地址:https://resonance-audio.github.io/resonance-audio/develop/unity/getting-started

图4.11 空间音频插件设置

4.6 高级渲染功能

本指南介绍了有助于提升性能的高级渲染功能。

4.6.1 注视点渲染

注视点渲染(Foveation Rendering)可以优化VR场景的渲染,该技术通过为视野中心提供全分辨率(无损),降低周边视野(人眼焦点区域之外)分辨率的方式来达到优化渲染的目的。静态注视点渲染(FFR)是指将视野焦点固定在视口中心位置,实现从中心向周围逐渐降低清晰度的效果。

图4.12 Foveation Rendering原理示意图

开启和配置"Foveated Rendering"选项如下图所示,在QiyuManager对象上QiyuManager.cs脚本中控制

图4.13 Foveation Rendering 配置界面

Foveation Level等级越高帧率越高,但是像素损失越多,会影响边缘区域清晰度,请根据渲染需要选择合适的等级。开发者也可以通过5.1提供的接口设置注视点渲染级别或自定义注视点渲染参数。

4.6.2 Multi View (Single Pass)

UnityXR提供了Single Pass立体渲染技术(https://docs.unity3d.com/Manual/SinglePassStereoRendering.html),通过一个Camera实现立体渲染,可降低50%的DrawCall,对于CPU占用高的场景帧率提升明显。

开发者可通过Project Settings->XR Plug-in Management->Qiyu,选择MultiView,该选项全局生效。

图4.14 MultiView选项

4.6.3 Vulkan 图形接口

Vulkan是一种现代图形API,与许多方面与OpenGL ES类似(OpenGL ES是奇遇3应用程序开发中使用的主要图形API),可以带来更好的CPU渲染性能,但无法提高GPU性能。

具体打开Vulkan设置的步骤如下:

打开Unity Editor > Build Settings > Player Settings > Settings for Android

找到Other Settings,勾掉 Auto Graphic API选项,在Graphic API下方添加Vulkan。

在Graphic API下将Vulkan排到OpenGLES上面。

图4.15 启用Vulkan

Vulkan已知问题

在我们的性能测试中,发现Vulkan API 大致相当于OpenGL ES性能,可能某些游戏的性能有一些提升,如果您的应用程序使用Vulkan时,相比OpenGL ES,性能有下降,请向我们提交错误,我们将评估修复。

Vulkan API目前为实验性质的功能,可能引起应用程序的中断或崩溃,如果您的应用程序使用Vulkan后没有出现问题,我们鼓励将项目升级到Vulkan。

Vulkan API不支持MutilView和FFR功能。

4.7 菜单功能

本指南介绍了奇遇提供的简化开发者部分工作的功能。提供入口Menu-Qiyu

图4.16 菜单功能

4.7.1 Modify Player Setting

一键自动修改工程配置至推荐配置,详细介绍参见快速入门步骤8

4.7.2 Create/Delete Manifest

如果开发者需要在Manifest文件中加入额外的内容(比如权限),可通过“Menu-Qiyu-Tools-Create Manifest”一键自动生成Manifest文件。详细介绍参见快速入门步骤9

五、接口说明

5.1 注视点渲染

注视点相关API

设置注视点等级

Utils.SetFoveationLevel((int)FoveationLevel.High);

设置注视点参数

Utils.SetFoveationParamets(30,30,30,30);

5.2 Boundary APIs

5.2.1 UnityXR

UnityXR提供了以下接口:

获取围栏点数据

UnityEngine.XR.InputDevices.GetDeviceAtXRNode(UnityEngine.XR.XRNode.Head).subsystem.TryGetBoundaryPoints(List boundaryPoints)

围栏改变监听事件

UnityEngine.XR.InputDevices.GetDeviceAtXRNode(UnityEngine.XR.XRNode.Head).subsystem.boundaryChanged

5.2.2 Qiyu

对于UnityXR未提供的接口,QiyuBoundary类开放了更多功能的接口,供开发者使用。

获取围栏是否是自定义围栏

public bool GetConfigured()

测试围栏中的Node结果

public BoundaryTestResult TestNode(Node node)

测试围栏中的Point结果

public QiyuBoundary.BoundaryTestResult TestPoint(Vector3 point)

获取所有围栏点集

public Vector3[] GetGeometry()

获取围栏尺寸范围

public Vector3 GetDimensions()

获取围栏是否可见

public bool GetVisible()

设置围栏常驻显示(系统设置中的围栏开关会覆盖此接口)

public void SetVisible(bool value)

六、平台解决方案

6.1 初始化

如果您需要使用奇遇平台功能,必须先按照以下内容初始化奇遇SDK:

API:

///

/// 初始化SDK

///

/// APPID

/// DeveloperID

/// App 秘钥

/// App 接口签名Key

public static void InitQiyuSDK(string app_id, string developer_id, string app_secret, string sign_key)

{

QiyuSDKCorePlugins.QVR_InitQiyuSDK(app_id, developer_id, app_secret, sign_key);

}

参数说明:

developer_id、app_secret、sign_key:将在商务为您分配开发者账号信息后自动生成,你可在登录奇遇开发者网站后,点击网站右上角“开发者名称”进入账户页面查看。

app_id:请您在登录奇遇开发者网站后,点击“发布管理—应用管理”创建您的应用,系统将会给每个应用生成唯一app_id。

注意:初始化接口必须在Start函数或后面的时机调用,不能在Awake函数里调用否则会崩溃

Demo :

//First, you need to monitor the SDK initialization result

QiyuMessageListener.AddListener(QiyuMessageCode.QiyuSdkInit, ret =>

{

QiyuPlugin.MessageResult msg = ret[0] as QiyuPlugin.MessageResult;

if (msg.IsSuccess())

{

}

});

//Initialize SDK

QiyuPlugin.InitQiyuSDK(

"70519169",

"820903",

"04c8f3a2d398a09debdb34902f278e2a",

"bc85d655c3416d5abdd98d4f7184fa22");

app初始化完毕后,开发者应该首先初始化sdk,来验证开发者身份,所有平台接口都需要身份验证成功后调用。否则会以下监听代码中返回初始化失败:

QiyuMessageListener.AddListener(MessageCode.QiyuSdkInit, ret =>

{

QiyuPlugin.MessageResult msg = ret[0] as QiyuPlugin.MessageResult;

if (!msg.IsSuccess())

{

///没有初始化成功的时候会调用

}

});

6.2 奇遇账户

在应用程序中获取奇遇用户的帐户状态和信息。

API:

///

/// 获取Qiyu账户是否登录

///

public static bool IsQiyuAccountLogin()

{

return QVRSDKCorePlugins.QVR_IsAccountLogin() == (int)Bool.True;

}

///

/// 获取Qiyu账户信息

///

/// 请求的回调函数

public static void GetQiyuAccountInfo(RequestCallback callback)

{

QiyuSDKCorePlugins.QVR_GetQiyuAccountInfo(QiyuMessageManager.AddRequest(callback));

}

Demo:

// Get Qiyu Account information

QiyuPlugin.GetQiyuAccountInfo(

RequestCallbackByJson>.Create((QiyuPlugin.MessageResult msg) =>

{

if (msg.IsSuccess())

{

Debug.Log("GetQiyuAccountInfo= " +msg.data.icon +" "+ msg.data.name +" "+ msg.data.uid);

}

}));

开发者在获取奇遇账号信息时,应先判断是否已经登录奇遇账号,只有登录成功后,才会获取到账户信息。

if (QiyuPlugin.IsQiyuAccountLogin())

{

QiyuPlugin.GetQiyuAccountInfo(

RequestCallbackByJson>.Create((QVRPlugin.QVRMessageResult msg) =>

{

if (msg.IsSuccess())

{

uid.text = msg.data.uid;

name.text = msg.data.name;

pic.text = msg.data.icon;

}

}));

}

else {

//跳转到Home进行登录

QiyuPlugin.LaunchHome("show", "login");

}

6.3 深度链接

当您有两个独立的应用程序时:例如一个单人游戏和一个多人游戏。如果你想要在两个应用程序中实现应用程序深度链接,用户可以从单人应用程序加入多人游戏应用。

深度链接需要在发出请求的应用程序和目标应用程序中进行集成。接下来的部分将描述这两个应用程序所需的实现。

API:

///

/// 打开其他应用

///

/// 应用id

/// 深度连接Key

/// 深度连接value

public static void LaunchOtherApp(string app_id, string key, string value)

{

QiyuSDKCorePlugins.QVR_LaunchOtherApp(app_id, key, value);

}

///

/// 获取深度连接信息

///

/// 回调函数

public static void GetDeepLink(RequestCallback callback)

{

QiyuSDKCorePlugins.QVR_GetDeepLink(QiyuMessageManager.AddRequest(callback));

}

Demo:

从A app 打开 B app, 调用LaunchOtherApp 并传入深度链接参数。

B app 在初始化完毕之后,调用GetDeepLink 函数获取之前传入的深度链接参数。

QiyuPlugin.LaunchOtherApp("70519169", "show", "1");

QiyuPlugin.GetDeepLink(

RequestCallbackByJson>.Create((QiyuPlugin.MessageResult ret) =>

{

}));

6.4 DLC

奇遇提供免费的DLC上传和下载服务,以帮助开发者减少APK的包体大小和用户的下载更新成本。

DLC上传

当您的安装包过大,用户下载应用的成本过高,例如一些图片、视频等需要和应用程序关联,奇遇为您提供了更简单的DLC资源文件上传(DLC文件必须是压缩文件,可最多支持上传5个,每个文件最大3.5G),您可以自由定义在哪些场景下需要去下载DLC文件,以减少APK大小。

同时DLC会关联APK的版本,那么该APK版本下的DLC可以支持随时更新,无需更新APK,以减少用户的下载更新成本。

获取DLC

您上传DLC文件后,您可以通过以下接口获取DLC信息

API:

///

/// 获取DLC更新信息

///

/// AppID

/// 当前应用版本

/// 回调函数

public static void GetAppUpdateInfo(string app_id, string curVersion, RequestCallback callback)

{

QiyuSDKCorePlugins.QVR_GetAppUpdateInfo(QiyuMessageManager.AddRequest(callback), app_id, curVersion);

}

Demo:

QiyuPlugin.GetAppUpdateInfo(

"70519169",

"1",

RequestCallbackByJson>.Create((QiyuPlugin.MessageResult msg1) =>

{

if (msg1.IsSuccess())

{

}

}));

获取到DLC信息后,由开发者根据DLC信息完成下载资源文件,并定义下载更新的场景和交互。此时用户在打开应用时,才能获取应用的完整功能和体验。

七、开发指南及常见问题

7.1 XR Rig的使用注意

如果游戏中有多个场景,每个场景都放置XR Rig,那么每次切换到新场景,都会自动重置position和rotation,TrackingOriginMode也会重新计算。

如果想要整个App只有一个XR Rig,可以制作一个启动场景放入XRRig,或者单例,然后调用GameObject.DontDestroyOnLoad让XR Rig保持不销毁。其他场景不放置XR Rig,这种情况在切换场景的时候可以保证position和rotation不被重置,TrackingOriginMode也不会重新计算。

如果不销毁XR Rig,需要同时保证XR Interaction Manager,QiyuManager同时不被销毁。

在使用单XR Rig的时候,如果跳转到其他场景中射线无法交互,则需要通过代码设置Canvas上的Event Camera,另外进入新的场景后需要重新初始化XRRayInteractor(可能是Unity的bug),这里我们只需要做一下隐藏和显示就可以了。具体示例如下,将该脚本挂载到UI Canvas上。

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using UnityEngine.XR.Interaction.Toolkit;

public class QiyuCanvasController : MonoBehaviour

{

Canvas canvas;

private void Awake()

{

canvas = GetComponent();

canvas.renderMode = RenderMode.WorldSpace;

canvas.worldCamera = Camera.main;

}

// Start is called before the first frame update

IEnumerator Start()

{

XRRayInteractor[] xRRayInteractor = FindObjectsOfType();

foreach (XRRayInteractor xrRay in xRRayInteractor)

{

xrRay.gameObject.SetActive(false);

yield return new WaitForEndOfFrame();

xrRay.gameObject.SetActive(true);

}

}

// Update is called once per frame

void Update()

{

}

}

7.2 老版本迁移

奇遇Unity SDK v0.4版本及以前版本迁移到UnityXR SDK v1.0.0版本时,必须删除老的SDK所有文件(QYVRSDK、QIVR Sample),再通过Unity Package Manager导入新的XR插件。

1.0版本统一规范了XR接口名称,在删除掉老版本SDK、导入XR sdk后,如果出现unity Editor Log报错,需要根据本开发文档和UnityXR开发文档,替换相应的接口名称。

挂在原“QVR Camera”预制体及其子物体上的脚本、组件,请根据需要移至“XR Rig”预制体上。

7.3 多语言AppName配置

如果需要不同系统语言下显示不同AppName,需要在打包的时候导入Android的多语言配置文件,在每个语言string.xml里配置不同app_name字段,多语言package例子可以从这里下载: