目录
前言
公司之前用的VRTK3.3,但是VRTK不支持SteamVR2.0.所以需要另外学习一个插件ViveInputUtility.
这是我的VRTK3教程,有兴趣可以看看.
Unity虚拟现实插件VRTK3.3使用教程一:基本配置_徐墨轩的博客-CSDN博客_vrtk教程
VIVE Input Utility | Integration | Unity Asset Store
https://github.com/ViveSoftware/ViveInputUtility-Unity
简单来说,vive只帮我们封装了VR必要的功能,方便了设备检测,传送,按键,UI交互等等,其他更复杂的功能就没有了.从功能上来说,没有VRTK提供的功能多,且没有VRTK3.3的文档详细.找来找去,只能找到git上wiki里的案例介绍.API似乎是没有专门做讲解.难怪VRTK3更让人喜欢.功能全,文档详细.
而且我找了一下CSDN,都是随便讲讲,唯一一个值得参考的就是这个链接了:
https://blog.csdn.net/obarong/article/details/52504638?ops_request_misc=&request_id=&biz_id=102&utm_term=ViveInputUtility&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-7-52504638.142^v40^pc_rank_34_queryrelevant0,185^v2^control&spm=1018.2226.3001.4187
下载
在unity商店里搜ViveInputUtility和SteamVR Plugin这两个插件.
ViveInputUtility其实就是对SteamVR 的封装.
下载安装后,点击vive的任意一个demo运行一下.结果又是要配置手柄,又是要选择用xr还是vr,根据提示自行判断就好.这里遇到一个问题,就是要求配置手柄按钮时,弹出的对话框点不掉.后来一直点点,就莫名其妙好了.demo也能正常运行了.
配置VR场景
不同设备不同平台需要做适配,还有vr中的基础互动操作这些工作都是由vive帮我们做过了.我们只需要使用他的预制体就ok了.
想看如果配置VR场景,直接运行vive第一个demo,场景里只有一个按钮.扣动手柄扳机键,可以触发按钮.
ViveCameraRig就像玩家本身,包括眼睛和手:查看VR场景必备
ViveRig:综合了ViveCameraRig,VivePointers,ViveColliders功能,并且还提供了激活按钮选项.(在案例6中)
ViveCurvePointers预制体抛物线,参考案例10;
瞬移
很简单.在场景的地板上挂上Teleportable,脚本可以选择瞬移的按钮.需要注意的是,地板必须有碰撞体.对应官方demo4
直线和抛物线
用哪个拖哪个.
UI交互
这个没什么好说的,在配置Player上也说了,只要在Canvas上挂CanvasRaycastTarget脚本,就可以当正常的UI开发.
交互(射线)
触碰
拾取
被拾取的物体身上必须要有碰撞体,刚体可加可不加.另外物体还需要挂上Draggable脚本.默认情况下,可以通过摇杆来控制物体的远近.
但是这个Draggable却不是Vive的核心脚本,只是demo场景中的脚本.如果能看懂这个脚本,或许你会收获良多.
交互(手)
//========= Copyright 2016-2022, HTC Corporation. All rights reserved. ===========
using UnityEngine.EventSystems;
namespace HTC.UnityPlugin.ColliderEvent
{
public interface IColliderEventHoverEnterHandler : IEventSystemHandler
{
void OnColliderEventHoverEnter(ColliderHoverEventData eventData);
}
public interface IColliderEventHoverExitHandler : IEventSystemHandler
{
void OnColliderEventHoverExit(ColliderHoverEventData eventData);
}
public interface IColliderEventLastHoverEnterHandler : IEventSystemHandler
{
void OnColliderEventLastHoverEnter(ColliderHoverEventData eventData);
}
public interface IColliderEventLastHoverExitHandler : IEventSystemHandler
{
void OnColliderEventLastHoverExit(ColliderHoverEventData eventData);
}
public interface IColliderEventPressDownHandler : IEventSystemHandler
{
void OnColliderEventPressDown(ColliderButtonEventData eventData);
}
public interface IColliderEventPressUpHandler : IEventSystemHandler
{
void OnColliderEventPressUp(ColliderButtonEventData eventData);
}
public interface IColliderEventPressEnterHandler : IEventSystemHandler
{
void OnColliderEventPressEnter(ColliderButtonEventData eventData);
}
public interface IColliderEventPressExitHandler : IEventSystemHandler
{
void OnColliderEventPressExit(ColliderButtonEventData eventData);
}
public interface IColliderEventClickHandler : IEventSystemHandler
{
void OnColliderEventClick(ColliderButtonEventData eventData);
}
public interface IColliderEventDragStartHandler : IEventSystemHandler
{
void OnColliderEventDragStart(ColliderButtonEventData eventData);
}
public interface IColliderEventDragFixedUpdateHandler : IEventSystemHandler
{
void OnColliderEventDragFixedUpdate(ColliderButtonEventData eventData);
}
public interface IColliderEventDragUpdateHandler : IEventSystemHandler
{
void OnColliderEventDragUpdate(ColliderButtonEventData eventData);
}
public interface IColliderEventDragEndHandler : IEventSystemHandler
{
void OnColliderEventDragEnd(ColliderButtonEventData eventData);
}
public interface IColliderEventDropHandler : IEventSystemHandler
{
void OnColliderEventDrop(ColliderButtonEventData eventData);
}
public interface IColliderEventAxisChangedHandler : IEventSystemHandler
{
void OnColliderEventAxisChanged(ColliderAxisEventData eventData);
}
}
触碰
在Vive里触摸不是touch,而是hover,如果一个物体想被触摸而触发事件,可以自定义脚本实现接口IColliderEventHoverEnterHandler
这里有OnColliderEventHoverEnter,OnColliderEventLastHoverEnter两种触摸进入接口.测试了一下,OnColliderEventHoverEnter进入触摸时只会触发一帧,但是OnColliderEventLastHoverEnter会触发好几帧.
碰了22次,OnColliderEventLastHoverEnter却触发了28次.不知道怎么算的.
按压
对着物体trigger键按下时,OnColliderEventPressEnter最先触发,接着OnColliderEventPressDown触发.
trigger键松开,OnColliderEventPressUp触发,最后OnColliderEventPressExit触发.
点击
对着物体点击trigger键,触发一帧
拾取
开始和结束都是一帧,update是每帧都触发.
需要注意的是,即使互动的3d物体没有加BasicGrabbable脚本,也会触发,但你会觉得怪怪的,正常开发拾取功能也不会这么做.
另外,在BasicGrabbable脚本上我并没找到物体是否被抓的判断,所以如果要判断该物体是否被抓住,或者被抓住时的逻辑处理.要么放在BasicGrabbable提供的After Grabbed事件函数上(1帧),要么只能自己新建脚本,继承对应接口来判断.
除了BasicGrabbable基础抓取的脚本外,vive还提供了另一种抓取脚本StickyGrabbable.(在场景5中体验)
StickyGrabbable效果是手松开,物体也不会放,再按一次按钮才会放.
StickyGrabbable多了个ToggleToRelease属性,就是来控制这个效果的.
扔掉
扔掉(松开手柄按键)的瞬间触发一帧.
综合案例
结合上面所讲,我们来写个demo:场景中一个按钮,一个桌子,按下按钮,桌子上会出现一把枪.拿起手枪,可以通过trigger键来发射子弹.
搭建的场景是这样的.
using HTC.UnityPlugin.ColliderEvent;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using HTC.UnityPlugin.Vive;
public class MyGun : MonoBehaviour
{
public Transform kou;//枪口的节点
public bool isGrab;
public float timerLimit = 0.5f;
public float bulletPower = 1000f;
private float t;
// Start is called before the first frame update
void Start()
{
float t = timerLimit;
}
// Update is called once per frame
void Update()
{
t -= Time.deltaTime;
if (ViveInput.GetPress(HandRole.RightHand, ControllerButton.Trigger) && t <= 0 && isGrab)
{
GameObject bullet = Instantiate(Resources.Load<GameObject>("Bullet"));
bullet.transform.SetParent(kou);
bullet.transform.localPosition = Vector3.zero;
bullet.transform.localRotation = Quaternion.identity;
bullet.transform.parent = null;
bullet.GetComponent<Rigidbody>().AddForce(kou.forward * bulletPower);
t = timerLimit;
}
}
public void IsGrab()
{
isGrab = true;
}
public void IsDrop()
{
isGrab = false;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using HTC.UnityPlugin.ColliderEvent;
public class MyPressBtn : MonoBehaviour, IColliderEventPressDownHandler, IColliderEventPressUpHandler
{
public GameObject gun;
public void OnColliderEventPressDown(ColliderButtonEventData eventData)
{
transform.position = new Vector3(1.52f, 0.58f, -2.47f);//下降位置
gun.SetActive(true);
}
public void OnColliderEventPressUp(ColliderButtonEventData eventData)
{
transform.position = new Vector3(1.52f, 0.665f, -2.47f);//初始位置
}
}
Input按钮
自定义设置按钮
使用
这个方法需要继承接口:IColliderEventPressEnterHandler
所有的HTC碰撞接口在HTC.UnityPlugin.ColliderEvent里.(在上文中交互(手)中有写)
像unity中Input那样获取手柄按键
if (ViveInput.GetPress(HandRole.RightHand, ControllerButton.Trigger))
这样获取可以了.第一个参数是左右手判断,第二个参数是按键判断.
但这和unity的input一样,如果不加判断,是全局的,在vr中我们会经常按键,所以我们总要去加个判断.
常见问题
如何设置左手柄抛物线移动,右手柄发射直线
- 添加VivePointers和ViveCurvePointers
- 将ViveCurvePointers上的 ViveInputVirtualButton脚本取消勾选(注意是取消右手柄的脚本)
- VivePointers的Left子物体失活
如何设置让直线不能参与瞬移
如何设置瞬移时,抛物线顶端的三角形提示变色
默认情况下,拖入Teleportable脚本到地板上不会自动设置,需要我们自己设置.
做一个提示面板跟着左手
如何判断一个物体被拾取了
可移动点和可移动区域
vive插件的案例中并没有这样的例子.但是steamvr里是有的.估计vive觉的太简单了,开发者可以直接用steamvr得了
动态传送到指定地点
常用脚本说明
https://blog.csdn.net/obarong/article/details/52504638?ops_request_misc=&request_id=&biz_id=102&utm_term=ViveInputUtility&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-7-52504638.142^v40^pc_rank_34_queryrelevant0,185^v2^control&spm=1018.2226.3001.4187
【Unity+Vive】第二篇:Vive Input Utility API详解_奥巴荣的博客-CSDN博客
ViveRoleSetter脚本:角色设置,用来设置该物体是什么角色.如手柄
官方案例说明
https://github.com/ViveSoftware/ViveInputUtility-Unity/wiki/Example-0.Tutorial
0.Tutorial
概述:就是一个空场景,只有一个Button,可以通过射线点击.
而Canvas上挂了一个脚本:CanvasRaycastTarget.这个脚本的用途就是,挂在Canvas上,Canvas就变成了VR可交互的UI.
1.UGUI
2.2DDragDrop
概述:拖动色块image,到指定面板或者3d物体上,可以改变其颜色.
3.3DDrag
概述:和2DDragDrop场景类似.只不过这是拖3d物体.另外,他还可以在拖拽的时候,通过手柄方向键来控制物体远近.一只手拽住的同时,另一只手抓住旋转也是可以的.
3d物体上挂上Draggable脚本.3d物体上要有刚体和碰撞体
4.Teleport
在场景的地板上挂上Teleportable,脚本可以选择瞬移的按钮.需要注意的是,地板必须有碰撞体.
另外比之前场景多了一个CustomDeviceHeight脚本.该脚本用来模拟玩家的高度.如果场景有物体比身高高,得蹲下来才能通过.
5.ColliderEvent
概述:这个场景主要是和场景中的3d物体交互.如触摸物体,拾取物体,按3d按钮,打开开关
可以被拾取的物体需要碰撞体,并且需要挂上脚本BasicGrabbable.这里物体添加刚体是为了模拟重力
注意:这里除了交互物体需要设置外,在玩家身上需要增加一个预制体ViveColliders.不然没效果
另外就是Sticky效果是手松开,物体也不会放,再按一次按钮才会放;而base的抓取就是手松开就会掉.
而Unblockable和Blockable,试了半天,没看出来区别.
6.ControllerManagerSample
概述:这个场景怎么玩,已经写在panel里了,按菜单按钮会显示激光射线,按trigger键可以抓住3d物体,按grip键可以显示自定义的手柄.其他和场景5类似.
一开始这个地方的VROrigin我没看懂.里面既没有VivePointers,也没ViveColliders.运行后却有射线,也能与3d物体交互.难道ViveControllers代替了这两个预制体?实验了一下,确实是的.而且从预制体中脚本配置也能看出来.
7.RoleBindingExample
8.NearFieldHandInteraction
概述:3d面板会跟踪玩家视野.并且3d面板上的按钮可以互动.
看脚本里是可以操作按钮的,但是不知道为啥,我手柄和按钮无法交互.不知道是不是需要案例7去做配置.
9.TrackedHandUGUIInteraction
这个和TouchPointers预制体有关,应该是通过手直接触摸UI的功能吧.
10.ControllerTooltips
概述:右手柄按菜单键(我这里是B键),可以呼出一个跟随的面板,此时,手柄变成了面板上的鼠标,可以选择不同的颜色按钮.确定后,场景中的"回"字会变颜色.
如果有项目需要呼出小面板,在小面板上选择按钮事件,可以参考这个demo
最后
如果有帮到你请一键三连:)
如果文中有错误的地方请指出,谢谢.