Introduction to VR Development
Introduction
Virtual reality (VR) is a simulated experience that employs pose tracking and 3D near-eye displays to give the user an immersive feel of a virtual world.
The equipment I am using now is Pico Neo3 based on PICO Unity Integration SDK
对于使用Unity开发, 其 XR Interactioin Toolkit 包已经提供了相当实用强力的脚本与抽象。本文会给出一些踩的坑和常见用法。
Environment:
Unity Editor 2021.3.5f1c1
Preview Tool provided by Pico Official
Notice
2.2.0中,XRKT提供了一些新的方法与属性, 一些旧版的被标记为弃用。本例中的代码可能有些无法在老版本中实现,但旧版一般也都提供了近似的方法与属性。
推测在使用Preview Tool时(有线连接),尤其是在PC端提示绿标“连接成功” 时,PC端的以太网会连接到一个”NDIS”设备,导致一些暂时的网络异常(无法访问网页)。
Interaction Toolkit
这可以被理解为使用Unity进行XR开发的核心,进行相关的配置后,几乎一切目前的VR设备可以被抽象为Unity的Device。XR Origin管理着这些设备。
在本文的项目中,直接使用了示例场景中的Introduction to VR Development.prefab
预制体,其已经配置好了XR Origin
,Input Action Manager
InteractionManager
EventSystem
等等基础的交互组件。
624b6fa1d9d4a945c593557a04b5a698.png
Interactor & Interactable
XRTK提供的主要交互方式为Interactor,可以大致分为
RayInteractor,Direct Interactor,Teleport Interactor三种,分别可以理解为射线交互,近距离的抓取抛掷交互,传送交互。其均继承自XRBaseControllerInteactor
类
可以被交互的物体需要挂载Interactable组件,并合理配置其Layer与Interaction Layer
Layer & Raycast Mask
即Inspector中右上角的Layer概念,可以控制对射线的遮罩。
Interaction Layer
配置Interactor可以交互的层,只有Interactable的Interaction Layer被包括在了Interactor的Interaction Layer中,Interactor才能与之交互。
例如:
CUBE 物体挂载的 Interactable组件中,勾选Interaction Layer为Deployable。并且CUBE的Layer 被囊括在Interactor中的Raycast Configuration -> Raycast Mask 中。
对应RayInteractor中的Interaction Layer囊括了此Deployable,那么CUBE可以被此Interactor交互。
e320974c3f47a8dd692c384abe24a8d8.png
498a2344f6b99fd75cf255dc921c6923.png
Events
Interactor 对物体的交互可以抽象为两种类型,即Hover(悬停,待选,摸),Select(选取,拿起,抓起)。每个类型又提供了Entered,Exited两个事件。
Development Practice
Assign Interaction Layer
通过代码指定Interaction Layer,在以下情况下,分别代表1 - Default 2 - Deployable
d5223dbaf91397bab58910ed077ae74e.png
1 | XRGrabInteractable xRGrabInteractable = gameObject.GetOrAddComponent<XRGrabInteractable>(); |
Bind Events and Handler Methods
绑定selectEntered
、selectExited
等等事件,Handler方法接受对应的EventArgs,以XRInteractorHoverEnteredHandler(HoverEnterEventArgs args)为例
1 | public class DragManager: SingletonForMonobehaviour<DragManager> |
获取当前交互的物体
1 | private void XRInteractorHoverEnteredHandler(HoverEnterEventArgs args) |
UI Elements
在UI组件上挂载TrackedDeviceGraphicRaycaster
,可以使得其接受对应的Hover、Select事件
Input Event
响应对应的按键。
Base Concepts & Models
以PICO Neo3为例:
43cc2a7be65a3d7abe62537ceab2e0b1.png
The table below describes the mappings between PICO controller buttons and Unity keys:
Button | Unity Keys |
---|---|
Menu | CommonUsages.menuButton : represents whether the Menu button has been activated (pressed). |
Trigger | - CommonUsages.triggerButton : represents whether the Trigger button has been activated (pressed). - CommonUsages.trigger : represents the degree to which the Trigger button was pressed. For example, in an archery game, it represents how full the bow has been drawn. |
Grip | - CommonUsages.gripButton : represents whether the Grip button has been activated (pressed). - CommonUsages.grip : represents the degree to which the Grip button was pressed. For example, in an archery game, it represents how full the bow has been drawn. |
Joystick | - CommonUsages.primary2DAxisClick : represents whether the Joystick has been activated (pressed). - CommonUsages.primary2DAxis : represents whether the Joystick has been moved upward, downward, leftward, or rightward. |
X/A | CommonUsages.primaryButton : represents whether the X/A button has been activated (pressed). |
Y/B | CommonUsages.secondaryButton : represents whether the Y/B button has been activated (pressed). |
Development Practice
下面给出了代码中获取到输入、事件的用法。
也许2.2.0的VRKT提供了相应事件,可以自行搜索用法。此处给出的代码参考PicoXR中的输入事件_窗外听轩雨的博客-CSDN博客 的内容。
Get Input Device
通过XRNode获取设备
1 | //XRNode为枚举变量 |
Try Get Input Value
1 | InputDevice device; |
InputEvent.cs
将输入转为事件,分离事件与处理逻辑。
1 | using System; |
Bind Events and Handler Methods
将对应的输入事件与处理事件想绑定,此处给出了Enter,Down,Up三个事件
private void BindXRInputEvent()
{
InputEvent.Instance.onLeftAXButtonEnter += AXButtonEnterHandler;
InputEvent.Instance.onLeftAXButtonUp += AXButtonUpHandler;
InputEvent.Instance.onLeftBYButtonEnter += BYButtonEnterHandler;
InputEvent.Instance.onLeftBYButonUp += BYButtonUpHandler;
}
private void AXButtonEnterHandler()
{
Debug.Log("[Input] LeftAXButtonEnter is called");
if (!hasStarted) return;
UIManager.Instance.OpenPanel(eUIPanelType.ChooseBluePrintPanel);
}
private void AXButtonUpHandler()
{
Debug.Log("[Input] LeftAXButtonUp is called");
if (!hasStarted) return;
UIManager.Instance.PopPanel();
}
Build
由于Neo3是安卓设备,在Unity打包时会遇到一些打安卓包的坑,主要原因是外网的一些资源不能正常访问。主要的解决办法时换源或者使用代理。
Introduction to VR Development
http://www.tsingloo.com/2022/11/05/bacd2918df354666bb1203a44435310e/