Unity VR(Pico)开发
最近入手了心仪已久的 VR-Pico Neo 3,价格还不错1900¥拿下,希望 Neo 4晚点出来哈,不然感觉会亏死!基于 Unity 引擎的基础 XR 场景,主要熟悉了一下Pico的SDK引入,手柄交互控制,2D UI交互之类的API。体验了一下其实用起来还蛮简单的,官方文档嘛一言难尽,先看看下面这些Demo呗。
基于PicoVR设备进行VR开发,记录几个Demo Code,用时随时查阅此博客和官方手册。
PicoVR SDK下载地址: https://sdk.picovr.com/developer-platform/sdk
PackageManager 安装插件:
设置Player的中的参数:Android API版本,L2CPP,ARM V8,XR Plugin选择Android,Build And Run选设备:
任意点传送 —— Area
新建地面 Plane,然后给地面标记可以传送:
XR Rig 就是表示玩家自己,XR Rig 就是Plane的Teleprotaion
XR Rig的组件属性设定如下:
Locomotion System组件就是负责整个玩家的移动,Provided只负责将Locomotion System和传送目标点绑定。
关于手柄的一些设置,比如设置射线颜色,触发按钮等等:
锚点传送 —— Anchor
Teleprotaion Anchor 用于锚点传送
如果需要改变传送的位置,先创建空对象,在把Teleprotaion Anchor Transform 设置为创建的空对象即可。
手柄控制视角 —— SnapTurnProvider
XR Rig添加SnapTurnProvider组件,指定控制移动的System即可:
隔空取物组件 —— XR Grab Interactable
地面需要开启碰撞,同时物体最好也设置刚体属性,扔出去的速度调节:Throw Velocity Scale
握住把手/开关门
先建造一个门,然后需要把手柄的射线给取消掉,即 XR Ray Interactor 这个组件需要被移除掉,同时下面两个组件 XR Interactor Line Visual 和 Line Renderer是用来描述射线的,也需要被移除。
给右手手柄添加碰撞器和手柄和交互器,同时为了表示左右手的模型,把手形状的预制体加进去,在 Packages - XR Plugin下面的 Prefab下可以找到:
C#脚本/手柄交互
用左手手柄控制小球运动的Demo Code:
1using System.Collections;
2using System.Collections.Generic;
3using UnityEngine;
4using UnityEngine.XR;
5using UnityEngine.XR.Interaction.Toolkit;
6
7public class PicoControllerOne : MonoBehaviour
8{
9 public XRController leftController;
10 // Start is called before the first frame update
11 void Start()
12 {
13
14 }
15
16 // Update is called once per frame
17 void Update()
18 {
19 // 获取左手控制器
20 Vector2 result;
21 bool success = leftController.inputDevice.TryGetFeatureValue(CommonUsages.primary2DAxis, out result);
22
23 if (success)
24 {
25 Vector3 position = transform.position;
26 // Time.deltaTime 帧间时间:为了移动更加平滑
27
28 float value = 0.2f;
29 transform.position = new Vector3(position.x + result.x * value * Time.deltaTime, position.y, position.z + result.y * value * Time.deltaTime);
30 }
31
32 // 握把键按下的值为多少(0 - 1之间的值)
33 leftController.inputDevice.TryGetFeatureValue(CommonUsages.grip, out float floatResult);
34
35 // 菜单键
36 leftController.inputDevice.TryGetFeatureValue(CommonUsages.menuButton, out bool menuClicked);
37
38 // 用这种方式也是OK的
39 InputHelpers.IsPressed(leftController.inputDevice, InputHelpers.Button.Grip, out menuClicked, 0.8f);
40 }
41}
2D UI绘制与界面
XR -> 创建Canvas
2D UI的点击事件,其实很简单和平时的Unity开发没什么两样,先弄一个空物体挂上脚本,里面写好点击事件回调或者其他回调,然后在Unity里绑定即可:
1using System;
2using System.Collections;
3using System.Collections.Generic;
4using UnityEngine;
5using UnityEngine.UI;
6
7public class UIController : MonoBehaviour
8{
9
10 public Text NumberText;
11 public Slider NumberSlider;
12 public void addNumberClick()
13 {
14 int num = Int32.Parse(NumberText.text);
15 NumberText.text = num + 1 + "";
16 }
17
18 public void subNumberClick()
19 {
20 int num = Int32.Parse(NumberText.text);
21 NumberText.text = num - 1 + "";
22 }
23
24 public void SliderChange(Single value)
25 {
26 NumberText.text = value + "";
27 }
28 // Start is called before the first frame update
29 void Start()
30 {
31
32 }
33
34 // Update is called once per frame
35 void Update()
36 {
37
38 }
39}
射线点击事件回调
XR Grab Interactable 会有抓取的效果,但是 XR Simple Interactable就只有回调,而不是抓取。
射线为照射到小球为灰色,照射到时为蓝色,按下为红色,取消变为蓝色,射线不照射小球恢复灰色的例子:
1using System.Collections;
2using System.Collections.Generic;
3using UnityEngine;
4using UnityEngine.XR.Interaction.Toolkit;
5
6public class SimpleInteractController : MonoBehaviour
7{
8
9 public GameObject gameObject;
10
11 public Material blue, red, grey, green, yellow;
12 // 选中点击按住
13 public void onSelected(XRBaseInteractor interactor)
14 {
15 gameObject.GetComponent<MeshRenderer>().material = red;
16 }
17 // 选中点击松开
18 public void onDeSelected(XRBaseInteractor interactor)
19 {
20 gameObject.GetComponent<MeshRenderer>().material = blue;
21 }
22
23 // 射线悬停在球上的时候
24 public void onHoverEnter(XRBaseInteractor interactor)
25 {
26 gameObject.GetComponent<MeshRenderer>().material = blue;
27 }
28
29 // 射线取消悬停在球上的时候
30 public void onHoverExit(XRBaseInteractor interactor)
31 {
32 gameObject.GetComponent<MeshRenderer>().material = grey;
33 }
34
35 // 选中时按下Trigger进入Active
36 public void onActived(XRBaseInteractor interactor)
37 {
38 gameObject.GetComponent<MeshRenderer>().material = yellow;
39 }
40 // 选中时松开Trigger进入DeActive
41 public void onDeActived(XRBaseInteractor interactor)
42 {
43 gameObject.GetComponent<MeshRenderer>().material = green;
44 }
45 // Start is called before the first frame update
46 void Start()
47 {
48
49 }
50
51 // Update is called once per frame
52 void Update()
53 {
54
55 }
56}