OpenXR+XR Interaction Toolkit 是 Unity 当前开发 VR 的一套比较通用且方便的解决方案。
近几年 XR(VR/AR) 行业的发展非常迅速,制造 XR 设备的厂商层出不穷。在早期“群雄纷争”的年代,不同的 XR 设备都维护着它们各自的 SDK,供开发人员制作出能在相应设备上运行的程序。但是尴尬的地方就在于,可能利用厂商 A 提供的 SDK 开发的程序无法兼容到厂商 B 的硬件设备上。不像如今已经比较成熟的安卓移动端,只需用 Android SDK开发一款程序,就能兼容到不同的安卓手机上。
因此开发者需要根据不同的 XR 设备厂商选择不同的 SDK 进行开发,这对于在不同设备上移植同一套程序是非常麻烦的,也大大提高了学习成本,比如用 Oculus SDK 开发的 VR 程序虽然能在 Meta Quest 上运行,但是如果想让使用 HTC Vive 的人也能使用该程序,就要把原先程序里运用 Oculus SDK 的部分替换成 HTC Vive 提供的 SDK,而市面上还有其他各种各样的 XR 设备,如果想要使用不同设备的人都能体验到我开发的程序,那岂不是要为每一种设备开发一个特定的程序版本?这显然是巨大的负担。而开发者希望 XR 行业能有一套统一的标准,只要编写一次代码,就能兼容所有的设备。这样开发者只要专注于程序开发本身,而不用在意设备间的差异。
而 OpenXR 就是为了简化 XR 开发而制定的一套标准。相当于在编写的 XR 应用程序和不同的硬件设备间新增了一个中间层,向上提供一套统一的开发 API,不同的开发引擎对该 API 进行二次封装,提供给 XR 应用开发者时使用。而不同的设备厂商为硬件编写支持 OpenXR 标准的接口,使得中间层能够向下兼容对应的硬件设备。如今,越来越多的 XR 设备开始支持 OpenXR 标准,这意味着选用 OpenXR 进行 XR 设备的开发可以成为一种通用的方案。
XR Interaction Toolkit 是 Unity 官方提供的开发 VR/AR 程序的框架,提供了移动、抓取、UI 交互等常用的功能,是游戏引擎提供给开发者的开发工具。
官方文档:https://docs.unity3d.com/Packages/[email protected]/manual/index.html(也许你在看到这篇文章的时候已经推出了更高的版本,那么你可以在官网中选择你正在使用的版本文档)
本篇教程将会利用 OpenXR 和 XR Interaction Toolkit 2.1.1 搭建一个简单的 VR 场景。最终实现的效果是开发者将 VR 头显和电脑进行串流后,能通过头显看到 Unity 中的场景,并且头部、手柄的位移和转动也能准确定位。
(注:本教程中的配置针对的是 PCVR 的开发,也就是头显和电脑串流的形式。如果是开发一体机的安卓应用,需要有其他的配置,但是这篇博客暂时不会介绍)
Unity 编辑器建议选用 2020 及以上的版本。虽然 XR Interaction Toolkit 2.1.1 支持 Unity 2019.4 及以上的版本,但是因为 2020 以其上的版本可以使用版本特有的 XR Plugin Management 更方便地管理 OpenXR,所以用 2020 及以上的版本配置起来更加简单。而且 XR Interaction Toolkit 后续的版本可能也不支持 2019 的版本了。
我这次使用的是 Unity 2020.3.36,VR 头显使用的是 Oculus Quest 2。
另外值得提醒的是本篇博客有可能具有时效性,因为 XR 更新迭代的速度比较快,目前尚不清楚 XR Interaction Toolkit 的功能和用法在未来会不会有比较大的变化,如果有,未来有时间也会进行教程的更新。不过目前来看,XR Interaction Toolkit 的版本大更新并不会太快,在我这几个月的使用期间,仅仅是一些名字有小改动,核心的用法是几乎不变的。
项目源码(持续更新):https://github.com/YY-nb/Unity_XRInteractionToolkit_Tutorial2022/tree/master
首先创建一个3D项目,虽然创建项目时选择 VR 模板会让 Unity 自动帮我们配置好一些东西,但是本教程将演示从零开始配置的方法,因此使用最普通的 3D 模板。
打开项目后在菜单栏选择 Edit -> Project Settings -> XR Plugin Management,然后点击 Install XR Plugin Management
安装完之后就是下面这个界面:
因为 Unity 中的 OpenXR 插件有用到新的输入系统 Input System,而创建项目时默认用的是旧的输入系统,我们这里选择"Yes”就能将输入系统替换成 Input System。然后界面会有一些新的变化:
接下来我们点击红框标注的这个“OpenXR”,会看到如下界面:
找到 Interaction Profiles,点击“+”可以添加想要兼容的设备。因为我是用 Oculus Quest 2 开发,所以我选择“Oculus Touch Controller Profile”
然后 Render Mode 的设置可以根据需求更改,我一般习惯把 Render Mode 中的 Single Pass Instanced 改为 Multi Pass。Multi Pass 会将场景渲染两次,分别显示在两只眼睛中,这种渲染方式虽然性能会差一点,但是具有高兼容性。想要了解这两种渲染模式的细节可以参考这篇文章(需要具备一定的图形学知识):VR MultiPass\SinglePass(Instanced)\MultiView 浅析和区分总结
打开 Unity 的 Window -> Package Manager,选择 Unity Registry,搜索 XR Interaction Toolkit,点击 Install
注:如果你是 Unity 2021 的版本但是发现 XR Interaction Toolkit 的版本不是最新的或者找不到这个包,可以试试点击下图所示的 “+” 号,选择 Add Package by name,输入 com.unity.xr.interaction.toolkit,即可导入。
不同的 Unity 版本可能导入 XR Interaction Toolkit 的方式会有点不一样,具体可以参考官方文档中的 Guides -> Installation。
然后导入 Samples 中 的 Starter Assets,这个包提供了 一些 Preset 和 Input System 中和 XR 有关的一些常用输入动作。
导入后我们可以看一下 Project 工作区,Assets 文件夹下多了几个文件夹:
其中 XR 是导入 OpenXR 后生成的,XRI 是导入 XR Interaction Toolkit 后生成的,Samples 是导入 Starter Assets 后生成的。
然后我们打开下图中的这个文件夹:
然后分别点击下图中红框标出的 Preset:
比如我现在点击第一个,查看 Inspector窗口,然后点击下图中红框标出的这个按钮。以后,在给一个 GameObject 添加 Continuous Move Provider(Action-based) 脚本后,脚本在 Inpector 面板的配置就会和这个 Preset 一样。
比如我现在想要随便给一个物体添加 Continuous Move Provider(Action-based) 脚本(这个脚本主要负责玩家持续移动,一般是利用手柄摇杆进行移动),如果我没有添加这个 Preset,那么脚本的面板配置是这样的:
添加 Preset 之后,再重新添加这个脚本,面板显示就会是这样(和 Preset 设置的是一样的):
按照 Starter Assets 中为我们准备好的 Preset 配置,可以大大简化我们后续的开发工作。因此,其他的 Preset 也是一样,我们都可以点击 Inspector 面板中的 Add 按钮。
接下来也是比较重要的一步,我们点击 Edit -> Project Settings -> Preset Manager:
找到 ActionBasedController,在 Filter 中分别填写 Right 和 Left,对应 Preset 中的 Right 和 Left Controller,如下图所示:
Filter 的作用
Controller 一般指的是手柄,XR Interaction Toolkit 提供了 ActionBasedController 这个脚本用于跟踪手柄的姿态和处理手柄的输入动作。先看一下这个脚本在 Inspector 面板中长啥样【实际上在面板中会显示为 XR Controller (Action-based) 】:
先不管每一个 Action 具体是什么意思(后面的教程会具体介绍,感兴趣的小伙伴也可以先看官方文档的这一部分:https://docs.unity3d.com/Packages/[email protected]/manual/xr-controller-action-based.html),目前我们需要知道的是这个脚本可以绑定配置好的动作,也就是添加这些 Input Action,那么配置的动作在什么地方呢?回到我们刚刚打开过的这个文件夹,打开下图的这个 Asset:
可以看到这里面有很多准备好的输入设置,比如上图中我现在选择的这个 XRI LeftHand Interaction,也就是左手交互相关的动作。其中的 gripPressed,也就是左手柄 grip 键按下的这个按键操作代表了 Select 这个动作,然后我们将这个 Select 动作绑定到 XR Controller (Action-based) 的 Selection Action 中,左手柄就能检测是否触发了“Select”这个动作,也就是左手柄的 grip 键是否被按下,这个功能经常用于 VR 中的抓取功能。
但是把动作一个个绑定到 XR Controller (Action-based) 中是比较麻烦的操作,不过别忘了左右手的 Controller 也有 Preset。
左:
右:
所以我们添加了 Preset 后,只要在 GameObject 上添加 XR Controller (Action-based) 脚本, Unity 会自动帮我们绑定好对应的动作。但是现在还有一个问题:怎么知道绑定的是左手还是右手? 所以 Filter 的作用就体现出来了,它会根据 GameObject 的名字来判断是左手还是右手。如果名字里含有 "Left“ 就根据 XRI Default Left Controller 这个 Preset 进行设置;如果含有 “Right” 就根据 XRI Default Right Controller 这个 Preset 进行设置。
那么现在基础的配置已经弄好了,接下来就来搭建一个简单的 VR 场景。
回到 Unity 的场景,首先把 Main Camera 删掉。然后在 Hierarchy 面板中点击鼠标右键 -> XR ->XR Origin(VR)
于是场景中会出现 XR Orgin 和 XR Interaction Manager
注:尚不清楚 XR Origin(VR) 这个名字在将来会不会更改,因为两个月前它还叫做 “XR Origin(Action-based)”,但是只要点击 XR 下的选项后能在 Hierarchy 面板中创建出这两个东西就行了
从上图中可以看到 XR Origin 下的 Camera Offset 有三个子物体,分别是主相机(XR Origin 下已经有了相机,所以我们之前要把场景中默认创建的主相机删掉),左控制器,右控制器。主相机对应 VR 头显,左控制器对应左手柄,右控制器对应右手柄,因此 XR Origin 正好就现实中的设备在 VR 世界中的映射,代表了玩家自己。然后我们可以看下左右手的控制器,我这里以左控制器为例:
可以看到左控制器的 XR Controller(Action-based) 脚本预先绑定了左手的动作。这是因为我们之前添加了左手控制器的 Preset,并且设置了 Filter。因为这个 GameObject 的名字里含有 Left,所以它能按照左手控制器的 Preset 来绑定动作。
此外,左控制器上还有其他脚本,这些脚本会在之后的教程中介绍。
如果左右手的控制器上的 XR controller(Action-based) 绑定的是正确方向的动作,说明之前的配置是成功的。
随便在一个 GameObject 上添加 Input Action Manager 脚本。我这里选择 XR Interaction Manager 这个物体,在 Inspector 面板中点击 Add Component,添加 Input Action Manager 脚本:
然后点击 Action Assets 下的 “+” 号,添加 XRI Default Input Actions:
然后在场景中添加一个 Plane,方便对照。到此,我们的场景就搭建完成了。然后我们将 VR 头显连上电脑,直接点击 Unity 编辑器的运行按钮进行测试(好像只有 Windows 系统可以):
可以看到此时已经处在 VR 的视角当中,随着头部的转动,视野也会改变,说明头部的追踪是正常的。
因为此时还没有手柄的模型,所以手柄处是空的。但是这两条红色的射线是由手柄发出的,如果射线能跟随手柄的位移和转动而运动,说明手柄的追踪是正常的。
如果大家看到的效果和我一样,那么就说明我们之前的配置是成功的!
本篇博客只是演示 OpenXR+XR Interaction Toolkit 开发 Unity VR 应用的基础配置。今后还会介绍更多 XR Interaction Toolkit 的功能,大家敬请期待~ 因为目前国内的相关教程还不是很多,所以我想把自己学习到的东西做个记录,分享给更多学习 VR 开发的小伙伴们!