前面几节我们了解了SteamVR的基本原理,现在可以进行实战开发了。但在进行VR开发前,我还要先介绍一套强大的VR开发工具——VRTK

在进行VIVE开发时,我们经常要用手柄进行一些操作,比如监听按键响应,通过手柄触摸板进行移动,抓取物体等等。这些交互功能实现起来其实不复杂,但是如果我们自己一个个去写又比较麻烦,为了避免重复造轮子,github上便有了vrtk这套SteamVR开发的工具集。

获取vrtk有两种方法
①gitHub的地址:https://github.com/thestonefox/VRTK
②在AssertStore中导入VRTK插件包

但是当我们把VRTK下载下来之后就头疼,这个工具集非常的庞大,由于开发人员也有很多,上面有很多代码甚至是冲突的,也没有一套很详细的说明文档,用起来非常不方便。

所以我们是没必要将这套VR开发工具集全部下载下来的,我们只需要选择里面我们需要的工具类下载下来使用就好了。我选择了下图中几种比较常用的工具类,并且选择几个类来进行源码分析。

第一个常用的工具类是VRTK_ControllerEvents,我们只需要把这个脚本挂到手柄控制器上,就能方便的获取到所有的按键状态。

在介绍这个类之前,我前讲讲我们是如何在SteamVR中获取按键并且响应的。HTC VIVE的手柄如下

HTC手柄的按键数据结构如下

    public class ButtonMask{public const ulong System;          // 保留按键public const ulong ApplicationMenu  //菜单按钮,对应图中的①public const ulong Grip             //手柄按钮,对应图中的⑧public const ulong Axis0            public const ulong Axis1            public const ulong Axis2        public const ulong Axis3            public const ulong Axis4            public const ulong Touchpad         //触控板,对应图中的②public const ulong Trigger          //扳机按钮,对应图中的⑦}

想要获取手柄的按键状态,得先拿到手柄的索引,获取索引有两种方法

/*IVRSystem是SteamVR SDK中的一个接口,可以通过OpenVR.System或者SteamVR.hmd来访问,比如获取左手的索引*/
IVRSystem.GetTrackedDeviceIndexForControllerRole(ETrackedControllerRole unDeviceType)/*获取左手柄的索引*/
uint leftIndex
=OpenVR.System.GetTrackedDeviceIndexForControllerRole(ETrackedControllerRole.LeftHand);/*获取右手柄的索引*/
uint rightIndex = OpenVR.System.GetTrackedDeviceIndexForControllerRole(ETrackedControllerRole.RightHand)

/*SteamVR_TrackedObject是挂载在手柄和头显上用来跟踪位置的脚本,在之前的文章中我讲过,这个脚本中记录了当前设备的索引*/
uint index=SteamVR_TrackedObject.index;

获取到手柄的索引后,我们就可以在update中通过下面的代码来监听按键了

/*这里的index就是我们前面获取的设备索引*/
var device = SteamVR_Controller.Input((int)index);/*
这里输入我们之前提到过的按键数据结构
SteamVR_Controller.ButtonMask.Trigger 对应扳机键
SteamVR_Controller.ButtonMask.ApplicationMenu 对应菜单键
……
*/
device.GetTouchDown(SteamVR_Controller.ButtonMask.Trigger)

知道了如何监听手柄的按键响应后,我们在来看看这个VRTK_ControllerEvents这个手柄控制工具类

脚本的开头定义了一系列的委托,通过代码可以看到,都是手柄的交互委托,我们只需要注册这些委托事件的回调,就能很方便的获取我们想要监听的按键操作。

我们在来看看它的实现代码

void Update()
{/*因为这个脚本是挂载在手柄下的,所以直接通过SteamVR_TrackedObject来获取索引,trackedController就是SteamVR_TrackedObject脚本*/ controllerIndex = (uint)trackedController.index;device = SteamVR_Controller.Input((int)controllerIndex);/*对于轴设备,则提供了一个GetAxis函数,返回值是一个Vector对象,分别提供X、Y两个维度的轴数据(扳机键只有X轴这个维度)*/Vector2 currentTriggerAxis=device.GetAxis(Valve.VR.EVRButtonId.k_EButton_SteamVR_Trigger);Vector2 currentTouchpadAxis = device.GetAxis();/*在Device里面为每个按键定义了三种状态:Press、PressDown和PressUp。分别通过GetPress、表示按键是否松开。对于触摸设备,也定义了GetTouch、GetTouchDown和GetTouchUp三个函数分别获取是否在触摸设备上按下、持续按下及松开。*///监听扳机键if (device.GetTouchDown(SteamVR_Controller.ButtonMask.Trigger)){OnTriggerPressed(SetButtonEvent(ref triggerPressed, true, currentTriggerAxis.x));EmitAlias(ButtonAlias.Trigger, true, currentTriggerAxis.x, ref triggerPressed);}else if (device.GetTouchUp(SteamVR_Controller.ButtonMask.Trigger)){OnTriggerReleased(SetButtonEvent(ref triggerPressed, false, 0f));EmitAlias(ButtonAlias.Trigger, false, 0f, ref triggerPressed);}else{if (Vector2ShallowEquals(triggerAxis, currentTriggerAxis)){triggerAxisChanged = false;}else{OnTriggerAxisChanged(SetButtonEvent(ref triggerAxisChanged, true, currentTriggerAxis.x));}}//监听菜单键if (device.GetTouchDown(SteamVR_Controller.ButtonMask.ApplicationMenu)){OnApplicationMenuPressed(SetButtonEvent(ref applicationMenuPressed, true, 1f));EmitAlias(ButtonAlias.Application_Menu, true, 1f, ref applicationMenuPressed);}else if (device.GetTouchUp(SteamVR_Controller.ButtonMask.ApplicationMenu)){OnApplicationMenuReleased(SetButtonEvent(ref applicationMenuPressed, false, 0f));EmitAlias(ButtonAlias.Application_Menu, false, 0f, ref applicationMenuPressed);}//监听抓取键if (device.GetTouchDown(SteamVR_Controller.ButtonMask.Grip)){OnGripPressed(SetButtonEvent(ref gripPressed, true, 1f));EmitAlias(ButtonAlias.Grip, true, 1f, ref gripPressed);}else if (device.GetTouchUp(SteamVR_Controller.ButtonMask.Grip)){OnGripReleased(SetButtonEvent(ref gripPressed, false, 0f));EmitAlias(ButtonAlias.Grip, false, 0f, ref gripPressed);}//监听按压Touchpadif (device.GetPressDown(SteamVR_Controller.ButtonMask.Touchpad)){OnTouchpadPressed(SetButtonEvent(ref touchpadPressed, true, 1f));EmitAlias(ButtonAlias.Touchpad_Press, true, 1f, ref touchpadPressed);}else if (device.GetPressUp(SteamVR_Controller.ButtonMask.Touchpad)){OnTouchpadReleased(SetButtonEvent(ref touchpadPressed, false, 0f));EmitAlias(ButtonAlias.Touchpad_Press, false, 0f, ref touchpadPressed);}//监听触摸Touchedif (device.GetTouchDown(SteamVR_Controller.ButtonMask.Touchpad)){OnTouchpadTouchStart(SetButtonEvent(ref touchpadTouched, true, 1f));EmitAlias(ButtonAlias.Touchpad_Touch, true, 1f, ref touchpadTouched);}else if (device.GetTouchUp(SteamVR_Controller.ButtonMask.Touchpad)){OnTouchpadTouchEnd(SetButtonEvent(ref touchpadTouched, false, 0f));EmitAlias(ButtonAlias.Touchpad_Touch, false, 0f, ref touchpadTouched);}else{if (Vector2ShallowEquals(touchpadAxis, currentTouchpadAxis)){touchpadAxisChanged = false;}else {OnTouchpadAxisChanged(SetButtonEvent(ref touchpadTouched, true, 1f));touchpadAxisChanged = true;}}//保存当前触摸板和扳机键的轴数据touchpadAxis = new Vector2(currentTouchpadAxis.x, currentTouchpadAxis.y);triggerAxis = new Vector2(currentTriggerAxis.x, currentTriggerAxis.y);
}

到这里,我们已经了解了如何监听HTC VIVE的手柄按键,也知道了VRTK_ControllerEvents的这个工具类的实现代码,在后面的章节里,我将陆续分析其他几个常用工具类的源码。

HTC VIVE开发教程(五)相关推荐

  1. HTC VIVE开发教程(一)

    在这一节,我介绍的主要内容有 HTC VIVE的安装与入门 VIVE插件的结构目录 学习VR有一段时间了,在这段时间里我对HTC的vive还有Oculcus都进行过一定的研究,也开发出了几款VR项目, ...

  2. HTC VIVE开发教程(二)

    这一节我介绍的主要内容有 SteamVR渲染机制 用Unity做游戏开发的核心之一就是图形渲染,做VR开发当然也是一样,在这一节,我们就来看看SteamVR的图形渲染原理.SteamVR_Render ...

  3. HTC VIVE开发教程(四)

    从这一节起我开始介绍一些vive的交互实现方式,比如手柄发出的射线,凝视,瞬移等等.SteamVR插件内都有这三种交互的辅助类. Extras文件夹里面的SteamVR_GazeTracker是凝视的 ...

  4. HTC VIVE开发教程(三)

    在这一节,我介绍的主要内容有 [CameraRig]预制体 [SteamVR]预制体 [Status]预制体 在SteamVR插件的Prefabs文件夹下面有三个预制体,CameraRig是相机预制体 ...

  5. HTC VIVE开发实例教程-邵伟-专题视频课程

    HTC VIVE开发实例教程-1971人已学习 课程介绍         HTC VIVE开发实例视频培训教程,我们相信学习VR技术与学习任何其它技术具有相通性,通过一定的刻意练习,后发现一个方法论和 ...

  6. HTC Vive 开发(一)——VR环境搭建

    VR环境搭建 第一步:创建空的Unity项目,并依此导入 SteamVR 和 VRTK 插件包 (有顺序是因为VRTK是依赖于SteamVR的,顺序颠倒可能会出现error) 第二步:创建空物体并命名 ...

  7. 公众号第三方平台开发 - 教程五 代公众号发起网页授权源码

    教程导航: 微信开放平台 公众号第三方平台开发 教程一 平台介绍 微信开放平台 公众号第三方平台开发 教程二 创建公众号第三方平台 微信开放平台 公众号第三方平台开发 教程三 一键登录授权给第三方平台 ...

  8. unity HTC vive开发笔记二

    今天来介绍 HTC vive开发之操作GUI 也就是实现手柄对物体的点击 Step 1 安装好我们需要的两个插件之后 删除我们的mainCamera 加入 assets-steamvr-cameraR ...

  9. HTC Vive unity 教程【转载】

    原文:HTC Vive Tutorial for Unity 作者: Eric Van de Kerckhove 译者:kmyhy HTC Vive 是一个虚拟现实头盔,由 HTC 和 Valve 公 ...

最新文章

  1. 2014年MCM美国大学生数学建模——From my perspective
  2. 他,16岁辍学创业,如今已身家过亿!今年将实现飞向太空的梦想
  3. JVM(一) ---JVM的数据模型
  4. jQuery的祖先遍历
  5. MVC架构中,用户的请求简单梳理
  6. video 微信 标签层级过高_什么是微信小程序二级分销系统?如何玩转?
  7. 安卓学习笔记42:基于HTTP网络编程
  8. 愤怒的小鸟,弹弓效果
  9. 注册flash.ocx inno setup (转)
  10. 程序员的终极幻想(一):像操作数据库那样操作大脑的记忆
  11. 区间dp讲解之石子合并问题 区间dp的分析方法
  12. CF1051D Bicolorings
  13. 《算法设计与分析》期末不挂科
  14. mbedtls基础及其应用
  15. 用Python进行web开发需要学习什么?
  16. 视频流媒体服务器ONVIF探测和云台控制是如何设置的?
  17. 【福利】免费领取企业信息查询两年VIP会员
  18. 用少量箭射爆气球,leetcode习题
  19. PostgreSQL高可用中间件—Pgpool-Ⅱ
  20. [LeetCode] 871. Minimum Number of Refueling Stops

热门文章

  1. 安装算量软件布套管操作
  2. DirectoryInfo和FileInfo
  3. PHP连接ACCESS(MDB)数据库的时候中文乱码问题的解决方案
  4. XmlDocument
  5. 梁肇新 编程高手箴言 书评
  6. 单臂路由实现VLAN间通信(不同VLAN,不同网段互访)
  7. 更换计算机电源线,由更换电源引发的一次理线记录
  8. stock 当天盘势
  9. 求1000的阶乘c语言编程,[原创] 1000的阶乘的程序代码,好题大家分享
  10. 联发科十核处理器跑分达8.6万:接近麒麟950