怎么用Unity微信开发工具怎么用HTC Vive

HTC VIVE基础开发文档(Unity3D)_图文_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
HTC VIVE基础开发文档(Unity3D)
阅读已结束,下载文档到电脑
想免费下载更多文档?
定制HR最喜欢的简历
下载文档到电脑,方便使用
还剩10页未读,继续阅读
定制HR最喜欢的简历
你可能喜欢unity中如何使用htc vive设备
,找到了,分享给需要的VR同学
要评论请先&或者&扫一扫,访问微社区
后使用快捷导航没有帐号?
签到成功!您今天第{todayrank}个签到,签到排名竞争激烈,记得每天都来签到哦!已连续签到:{constant}天,累计签到:{days}天
当前位置: &
查看: 2309|回复: 3
使用HTC Vive和Kinect开发联网VR游戏
16排名<font color="#FF昨日变化主题帖子积分
蛮牛币47378
在线时间3282 小时
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
才可以下载或查看,没有帐号?
7.jpg (38.77 KB, 下载次数: 4)
09:11 上传
看到Jasper Brekelmans和Jeroen de Mooij的新实验成功使用HTC Vive和微软Kinect远程将两个玩家投映到虚拟世界中之后,我们非常希望知道他们是如何办到的。所以在他们自己的一个采访视频中,这两位分享了他们的开发秘诀,在VR内使用HTC Vive和微软Kinect相机的忧虑和开心。
8.jpg (55.9 KB, 下载次数: 1)
09:12 上传
当Jasper Brekelmans和小伙伴Jeroen de Mooij得到了一套HTC Vive设备之后,他们希望能够开发一个应用来实现他们的理念,“虚拟现实革命需要一点社交元素才能真正成气候”。所以他们决定制作一款多玩家合作式VR游戏,而且这个游戏不仅要能允许在VR内分享和投映物理空间,而且还要能投映玩家的身体。而这个结果就是一个看上非常酷炫的分享体验,而且仅在VR内可行。
我们希望这两位能够分享他们的经验,因而Jasper和Jeroen就互相采访来揭秘为什么会有这个项目,这个项目是如何变成现在这样以及最后是如何执行的。
9.jpg (26.35 KB, 下载次数: 0)
09:12 上传
Jasper Brekelmans
Jasper(@brekelj)15年前入行时时一位动作捕捉职业人员和3D角色装配师,主要为商业广告,电视揭幕,电影和互动角色工作。也许你知道他是因为他创造了Brekel工具组,一个提供简单亲民的Kinect传感器无标记动作捕捉的工具。
10.jpg (29.44 KB, 下载次数: 0)
09:13 上传
Jeroen de Mooij
Jeroen(@jeroenduhmooij)起初是一名交互设计师,不过几年后他的工作重心逐渐转向了制作3D内容。一开始是动画,现在则主要是为了互动。他还为广告,互动装置和大型视频投映绘制以及定制化软件和工具工作。
当你们启动项目时,目标是什么?
Jasper:我们拿到两个借来的Valve/HTC Vive头戴式设备时想做的第一件事就是在假期的时候爽一把。很快我们就冒出了一个小小的黑客马拉松计划,先看看是否能搞出一个多用户设置。因为我们只有一套Lighthuse基站,所以我们只能选择让两个用户共享一个虚拟和现实空间。
我们想看看我们是不是能够想出一个虚拟场景用户可以在其中合作构建/操控某个东西同时也能看到另一个用户以及他/她对于这个虚拟场景的贡献。我们希望所有的数据都能通过网络连接共享这样我们以后可能有机会进一步拓展这个。
Jeroen:由于我们拥有两个HTC系统有时间限制,我们的方法就是在那段时间之内能走多远走多远。
所以第一个是,我们能不能在2个Lighthouse基站的范围内连接两台头戴式设备?试了一下没问题。那么多用户环境要怎么设置呢?所以我们基本就是在过程中不断设立新的目标,但是我们一开始就希望能过做一个多用户体验。
11.jpg (43.14 KB, 下载次数: 0)
09:14 上传
谁干了什么?
Jasper:我主要负责点云的可视化,通过我的Brekel专业版点云应用写一个可以压缩和流传输实时数据的代码并在Unity DirectX11着色器内渲染它。
低延迟也非常重要,获得并以30帧率来渲染点云数据(这是Kinect原生的帧频),同时不拖慢Unity的视点渲染(一般VR在60-90帧率左右)并且占用的带宽还不能比目前网络连接所能处理的更多。
不过幸运的是所有这些目标都通过多执行绪C++代码和通过使用DirectX11着色器直接读取GPU图形处理器实现了。Marald Bes也帮我们写了一个Unity代码使得虚拟物体可以拾取和操纵。
Jeroen:我用工作已经有一段时间了而且最近在弄一个涉及到工作站和Gear VR联网的小心测试,所以我知道Unet系统的一些基本信息。
基本上所有Unet相关的连接我都是在Unity3D里面完成的并且设置了游戏的场景。Marald帮忙写了怎么通过Steam的控制器抓取盒子的代码。
然后我用了另一个与Erwin合作的研发项目的角色头部,Jasper则负责他最擅长的部分,那些Kinect相关的东西(流传输服务器啊,连接啊,客户端啊之类的)。
你们在安装启用的时候遇到过什么问题吗?
Jasper:问题?当然没有,我们第一次尝试的时候所有东西都非常顺利…我们连一次咒骂都没有过…没错就酱:)
启用连接代码一直是很困难而且很糟心的工作,一开始我为了性能使用的都是原始套接字。试了两次之后证明要让那个变得很强悍太难了,所以最后我还是在一个现存程序库的基础上构建而且最后还带来了一些意想不到的性能福利。
对于Unity DirectX11着色器就幸运一点了,我一部分可以依赖一些我以前编号的代码,所以那个很顺利。我倒是用程序上在GPU图形处理器上生成的网格渲染风格拓展了点云的渲染。
在安装启用的时候我们发现点云风格其实看上去更好,因为网格时不时会切断挡住太多视线的东西。匹配点云和两个Vive校准事实证明也很棘手,但是我们尝试了几次后发现了一些实用窍门来良好匹配东西以便测试。
Jeroen:时间,时间是一个非常大的因素,特别是最后期限在即的时候,但是另一方面它也会让你非常专注于那段时间内要实现的东西。
我有如何在Unity3D里构建单人体验的经验但是没有怎么做过连接或者多用户的项目,我真的需要时间来搞明白Unet设置的方式和用来干什么。所以这意味着经常会忙得团团转之后又得以一个新的切入点重新开始。此外,资料和教程都很有限,因为Unet系统是一个新加入Unity3D的功能,而且,一如既往,我希望尝试的东西都不属于“基本”功能。
对了,我还注意到控制器有时在电量充足的情况下也会下线。
Steam系统的排字符有时会有点困惑,一般在不担心把一个窗口拖到第二个屏幕的时候会发生。(HTC Vive)
12.jpg (37.69 KB, 下载次数: 1)
09:15 上传
你们在玩转该技术的时候学到了什么,有什么是你们一开始没有预料到的吗?
Jasper:首先而且也是最重要的是,比我们原来想得要有趣得多:)
而且很多事情水到渠成我都没有想过。比如可以把拾取的物体从一只手送到另外一只,把它扔给另一个用户然后他抓住它。
而且与另一个用户的非语言交流,从只是简单地看看他在干什么,到手势这类东西都非常本能直观易于沟通。
此外向对方的脸扔方块也很(尽管这个我们应该有预料到)而且做得出乎意料的话甚至还能触发真实的躲避反应。
Jeroen:我学会了叠盒子:)
用过DK2和Gear VR之后我知道大脑很容易被误导。
在这个试验中最大的感受是感觉上很自然。点云不止能够再现另一个人,而且还能再现一些环境点。所以对我来说,完全没有和现实世界断裂的感觉。老实说我没有预料到那个,完全出现在另一个世界完成SteamVR的演示。这自然就有它自己的魅力。
对我来说连接线并不是一个问题,我很快就习惯了它。不过如果脑袋后面可以没有这个协同程序的话会是很大的进步。
有机会去四处走动,尤其是在绕着一个3D物体走动,给虚拟世界带来很大的自由感。这真的与我之前有过的所有坐式体验都完全不同。
13.jpg (56.03 KB, 下载次数: 0)
09:16 上传
你们的未来计划是什么?
Jasper:我们当然想拓展这个设置,当两个用户没有共享同一个物理空间而是在两个不同的办公室使用互联网连接的时候。
不幸的是我们不得不把借来的Vives物归原主所以大概得等到零售版本面市以后吧:(
我们也很期待把这个改编应用到混合现实设备上,比如微软的HoloLens,因为我们相信这种共享3D物体的合作在提高产能方面大有用处。
Jeroen:希望能够拓展这个项目或者启动类似的VR/AR/MR实验。
对于这个项目我希望能够增加一些东西,比如在互联网上做这个然后看看感觉如何。如果是那样的话增加位置化声音就很重要。
此外我对于同一空间内更多用户分享和合作某个东西会如何也很好奇,我当然能看到游戏的潜力,不过我认为对于各种各样的目的来说都有很多机会。叠盒子扔盒子很有趣,那么任何物理沙盒都是如此,但是我希望能在这样的环境中拓展功能。也许给每个用户自己的一套工具来更进一步刺激合作。
在环境中加入更多的点云数据流传输是另一件事,此外还有确保Kinect角度和范围的设置没有问题,甚至可能会去看一眼Jasper在做的另一个项目,多重Kinect云数据。
14.jpg (62.33 KB, 下载次数: 5)
09:16 上传
为什么要在设置中使用一个Kinect设备?
Jasper:我们只是为了用点云,没有使用它的任何骨架跟踪功能。
我之前试验过VR内渲染3D角色(使用Kinect以及其他动作捕捉设备)。
它还不错而且显然有它的好用之处,但是鉴于3D角色始终是用户的抽象再现,因此沉浸感不是很好。
尽管一个点云再现也有人工感,但是它包含一些质感,光影和细节可以让你知道只属于这个用户(你或者另外一个人)而我们注意到相比抽象的再现,你可以从中注意到更多细微的线索。
Jeroen:Jasper之前就在做一个点云流传输相关的小型项目,所以把这个加入试验中的时机刚刚好。
它真的非常有助于为整个实验增加“真实性”。Vive能够追踪控制器和头戴式设备,所以只有手部和头部,而不是整个人的再现。但是给SteamVR匹配了Kniect的合作系统之后,就有一整个人站立在VR之中了。而且点云身体加上3D角色的脑袋真的看上去很好玩。
我们为什么要使用这个沙盒?(下一次更出色的沙盒会是什么样的呢?)
Jeroen:四处扔东西不是很好玩吗?我们也是这么认为。除了物理定律使得结合物体更容易之外也能够支持一起工作。
周边物体就在那里,可以向它们扔盒子,然后我们就会知道连接的同步性是不是像我们想的那样运作良好。
下一次我希望能够更加专注于某种目的的合作。比如在地图上放置建筑物并运行一个模拟,或者为某种三维谜题寻找解决方案之类的。
你们能分享关于所使用的设置的更多细节吗?
Jeroen:我们用了两个工作站,一个i5一个i7,两个都有GTX970英伟达卡。只用了两个Lighthouse基站用于追踪。这个项目主要在Unity3D,5.3版里制作。
Jasper:还有Kinect第二版传感器:)
花了多久来研发呢?大概让它能运转花了多少时间?
Jasper:我们一起在办公室里呆了三天,然后我另外花了一周在连接课上编程。
Jeroen:我在另外一个项目上有一个已经完成设置好的VR系统,所以在我们开始的时候这个就可以用。我拿到了另一个Vive系统的时候第一个测试的就是在只有两个Lighthouse基站的时候它们是不是都能运作。
它们都运作良好,我们就开始讨论我们可以构建的各种机会,我主要专注于设置Unet相关的东西,算上反复试验大概花了几天。Jasper完成了点云流传输部分的准备工作然后我们花了两天把它们编辑在一起,然后又花了一天微调和拍摄。
如果我们有更多使用这个系统的时间,我们大概会在其中加入更多功能,但是这个设置基本是一周之内完成的。
这个设置仅限于Vive还是说其他VR系统也能适用,比如在手机端上(GearVR)?
Jasper:这个设置的确需要手部追踪和拾取东西的能力,以及头戴式设备的位置追踪也会很有用。
所以举例来说,我猜想Oculus Touch和HoloLens的手部姿势也能使用,而且这两个应该也能运行Unity和点云的DirectX11着色器。但是Gear VR缺乏这些东西,所以对于这个特定设置来说它显得没有那么有趣。
Jeroen:这其实,“不过”是一个多玩家环境,玩家可以在其中做一些事情。所以如果输入是Vive +Lighthouse基站,还是Kinect骨架或者是一个能够控制角色的有机动作追踪解决方案,一切且有可能。
如果能够加入外部位置追踪的话,那么考虑Wi-Fi环境下的Gear VR也是有肯呢个的。但是我们的目标是HoloLens。(虚拟现实游戏)
vive,非干什么的;学unity3d需要多久;虚拟现实还要多久;虚拟现实干什么;虚拟现实带宽要求;虚拟现实制作干嘛的;unity3d干什么;unity3d学要多久;unity3d要学多久;虚拟现实还有多久;虚拟现实大概多久;虚拟现实多久实现;虚拟现实可以干什么;虚拟现实以后干什么;虚拟现实带宽;虚拟现实制作干嘛
每日推荐:
回帖是美德~是一种行动认可和支持~希望更多蛮牛小伙伴参与到支持行动中~
5936/1000排名<font color="#FF昨日变化主题帖子积分
熟悉之中, 积分 936, 距离下一级还需 64 积分
熟悉之中, 积分 936, 距离下一级还需 64 积分
蛮牛币1204
在线时间351 小时
以后一定会火
每日推荐:
5791/1000排名<font color="#FF昨日变化2主题帖子积分
熟悉之中, 积分 791, 距离下一级还需 209 积分
熟悉之中, 积分 791, 距离下一级还需 209 积分
在线时间283 小时
果然是新闻。技术方面一点都没透露
每日推荐:
2108/150排名<font color="#FF昨日变化40主题帖子积分
初来乍到, 积分 108, 距离下一级还需 42 积分
初来乍到, 积分 108, 距离下一级还需 42 积分
在线时间26 小时
还打算进来看点干货呢,没透露啥技术细节啊
每日推荐:
七夕浪漫情人
2015年蛮牛社区浪漫七夕 最美情话活动获奖者
在“新人报到 ”版块发过自己的照片扫一扫,访问微社区
后使用快捷导航没有帐号?
签到成功!您今天第{todayrank}个签到,签到排名竞争激烈,记得每天都来签到哦!已连续签到:{constant}天,累计签到:{days}天
关注:1848
当前位置: &
__________________________________________________________________________________
开发者干货区版块规则:
  1、文章必须是图文形式。(至少2幅图)
& && &2、文章字数必须保持在1500字节以上。(编辑器右下角有字数检查)
& && &3、本版块只支持在游戏蛮牛原创首发,不支持转载。
& && &4、本版块回复不得无意义,如:顶、呵呵、不错......【真的会扣分的哦】
& && &5、......
__________________________________________________________________________________
查看: 9890|回复: 63
HTC Vive之Unity3d开发日记@3
73520/5000排名<font color="#FF昨日变化主题帖子积分
日久生情, 积分 3520, 距离下一级还需 1480 积分
日久生情, 积分 3520, 距离下一级还需 1480 积分
蛮牛币8673
在线时间712 小时
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
才可以下载或查看,没有帐号?
& && & & && && && &
关于火腿肠里面的UI我之前研究了一段时间,也和一些开发者朋友探讨了一下,常规的UI只会在电脑显示屏上渲染,而不会在眼镜里面渲染,我之前习惯使用NGUI,现在发现不得不转Ugui了,这里附上一个朋友发的博客:
写得蛮好,3d的Ugui是可以在眼镜里面渲染的,这里不再啰嗦!
vive_inputs.png (229.79 KB, 下载次数: 12)
19:26 上传
我们今天的主题还是手柄的交互,我谈一下自己的一些设置哈,大家不一定要照做,不过,是我自己认为最方便的:7.Trigger扳机我主要用来做确认:
[C#] 纯文本查看 复制代码using UnityE
using System.C
/// &summary&
/// 扳机控制触发事件
/// &/summary&
public class ComfirmController : MonoBehaviour {
SteamVR_TrackedObject trackedO
void Awake()
//获取手柄脚本组件
trackedObj = GetComponent&SteamVR_TrackedObject& ();
// Use this for initialization
void Start () {
// Update is called once per frame
void FixedUpdate () {
//获取手柄输入
var device = SteamVR_Controller.Input ((int)trackedObj.index);
//此处可以换其他的函数触发GetPress/GetPressDown/GetPressUp GetTouchDown/GetTouchUp/GetAxis
if (device.GetTouch (SteamVR_Controller.ButtonMask.Trigger)) {
//干点什么
当然,在射击游戏里面用来Fire开火最合适,和武器的扳机手感也是一致的!
BTW,也有朋友询问关于手柄震动的,我正好知道,后面的代码有解析.
至于传送呢,我采用的是Touchpad,按下的时候发射抛物线或者射线,松开的时候就传送过去,这样比较省按钮,而且也方便;我看有的游戏做的传送很不方便,按下圆盘触发传送后,还有一个预览,预览可以通过左右的Grip按钮来调整传送后的视角,个人认为是复杂化了;这样做不但实现起来麻烦,客户用起来也麻烦,关键在于反应速度,例如怪物已经离我很近了,我要逃跑的话手忙脚乱的用户就会狗带,如果采用我这种松开立即传送的机制就能及时拉开距离逃生!
菜单键是没有什么争议的,大多数都是用来调出菜单选项,然后通过左右的Grip来翻页,或者直接用另外一个手柄来操作当前菜单.
详细的我们来看看代码:
[C#] 纯文本查看 复制代码//========= Copyright 2015, Valve Corporation, All rights reserved. ===========
// Purpose: Wrapper for working with SteamVR controller input
//目的:封装来处理手柄输入
// Example usage:
//这个栗子是左手柄震动 右手震动只需把Leftmost换成Rightmost即可
// var deviceIndex = SteamVR_Controller.GetDeviceIndex(SteamVR_Controller.DeviceRelation.Leftmost);
// if (deviceIndex != -1 && SteamVR_Controller.Input(deviceIndex).GetPressDown(SteamVR_Controller.ButtonMask.Trigger))
SteamVR_Controller.Input(deviceIndex).TriggerHapticPulse(1000);
//=============================================================================
using UnityE
using Valve.VR;
/// &summary&
/// &/summary&
public class SteamVR_Controller
public class ButtonMask
public const ulong System
= (1ul && (int)EVRButtonId.k_EButton_System); // reserved 为Steam系统保留,用来调出Steam系统菜单
public const ulong ApplicationMenu = (1ul && (int)EVRButtonId.k_EButton_ApplicationMenu);
public const ulong Grip
= (1ul && (int)EVRButtonId.k_EButton_Grip);
public const ulong Axis0
= (1ul && (int)EVRButtonId.k_EButton_Axis0);
public const ulong Axis1
= (1ul && (int)EVRButtonId.k_EButton_Axis1);
public const ulong Axis2
= (1ul && (int)EVRButtonId.k_EButton_Axis2);
public const ulong Axis3
= (1ul && (int)EVRButtonId.k_EButton_Axis3);
public const ulong Axis4
= (1ul && (int)EVRButtonId.k_EButton_Axis4);
public const ulong Touchpad
= (1ul && (int)EVRButtonId.k_EButton_SteamVR_Touchpad);
public const ulong Trigger
= (1ul && (int)EVRButtonId.k_EButton_SteamVR_Trigger);
public class Device
public Device(uint i) { index = }
public uint index { }
public bool valid { }
public bool connected { get { Update(); return pose.bDeviceIsC } }
public bool hasTracking { get { Update(); return pose.bPoseIsV } }
public bool outOfRange { get { Update(); return pose.eTrackingResult == ETrackingResult.Running_OutOfRange || pose.eTrackingResult == ETrackingResult.Calibrating_OutOfR } }
public bool calibrating { get { Update(); return pose.eTrackingResult == ETrackingResult.Calibrating_InProgress || pose.eTrackingResult == ETrackingResult.Calibrating_OutOfR } }
public bool uninitialized { get { Update(); return pose.eTrackingResult == ETrackingResult.U } }
// These values are only accurate for the last controller state change (e.g. trigger release), and by definition, will always lag behind
// the predicted visual poses that drive SteamVR_TrackedObjects since they are sync'd to the input timestamp that caused them to update.
//这些值只在最近状态发生改变的才准确(例如 释放扳机),通过定义,将会总是在预测视觉动作(这个预测的信息用来驱动SteamVR_TrackedObjects)之后延迟,因为他们是和输入的时间戳同步更新的
public SteamVR_Utils.RigidTransform transform { get { Update(); return new SteamVR_Utils.RigidTransform(pose.mDeviceToAbsoluteTracking); } }
public Vector3 velocity { get { Update(); return new Vector3(pose.vVelocity.v0, pose.vVelocity.v1, -pose.vVelocity.v2); } }
public Vector3 angularVelocity { get { Update(); return new Vector3(-pose.vAngularVelocity.v0, -pose.vAngularVelocity.v1, pose.vAngularVelocity.v2); } }
//获取状态 之前的状态
public VRControllerState_t GetState() { Update(); }
public VRControllerState_t GetPrevState() { Update(); return prevS }
public TrackedDevicePose_t GetPose() { Update(); }
VRControllerState_t state, prevS
TrackedDevicePose_
int prevFrameCount = -1;
public void Update()
if (Time.frameCount != prevFrameCount)
prevFrameCount = Time.frameC
prevState =
var system = OpenVR.S
if (system != null)
valid = system.GetControllerStateWithPose(SteamVR_Render.instance.trackingSpace, index, ref state, ref pose);
UpdateHairTrigger();
//长按 按下
两种参数buttonMask buttonId
public bool GetPress(ulong buttonMask) { Update(); return (state.ulButtonPressed & buttonMask) != 0; }
public bool GetPressDown(ulong buttonMask) { Update(); return (state.ulButtonPressed & buttonMask) != 0 && (prevState.ulButtonPressed & buttonMask) == 0; }
public bool GetPressUp(ulong buttonMask) { Update(); return (state.ulButtonPressed & buttonMask) == 0 && (prevState.ulButtonPressed & buttonMask) != 0; }
public bool GetPress(EVRButtonId buttonId) { return GetPress(1ul && (int)buttonId); }
public bool GetPressDown(EVRButtonId buttonId) { return GetPressDown(1ul && (int)buttonId); }
public bool GetPressUp(EVRButtonId buttonId) { return GetPressUp(1ul && (int)buttonId); }
//触摸 按下
public bool GetTouch(ulong buttonMask) { Update(); return (state.ulButtonTouched & buttonMask) != 0; }
public bool GetTouchDown(ulong buttonMask) { Update(); return (state.ulButtonTouched & buttonMask) != 0 && (prevState.ulButtonTouched & buttonMask) == 0; }
public bool GetTouchUp(ulong buttonMask) { Update(); return (state.ulButtonTouched & buttonMask) == 0 && (prevState.ulButtonTouched & buttonMask) != 0; }
public bool GetTouch(EVRButtonId buttonId) { return GetTouch(1ul && (int)buttonId); }
public bool GetTouchDown(EVRButtonId buttonId) { return GetTouchDown(1ul && (int)buttonId); }
public bool GetTouchUp(EVRButtonId buttonId) { return GetTouchUp(1ul && (int)buttonId); }
//获取轴心 此处是用来返回手指在触摸板Touchpad上的位置
public Vector2 GetAxis(EVRButtonId buttonId = EVRButtonId.k_EButton_SteamVR_Touchpad)
var axisId = (uint)buttonId - (uint)EVRButtonId.k_EButton_Axis0;
switch (axisId)
case 0: return new Vector2(state.rAxis0.x, state.rAxis0.y);
case 1: return new Vector2(state.rAxis1.x, state.rAxis1.y);
case 2: return new Vector2(state.rAxis2.x, state.rAxis2.y);
case 3: return new Vector2(state.rAxis3.x, state.rAxis3.y);
case 4: return new Vector2(state.rAxis4.x, state.rAxis4.y);
return Vector2.
//上面提到的震动方法
public void TriggerHapticPulse(ushort durationMicroSec = 500, EVRButtonId buttonId = EVRButtonId.k_EButton_SteamVR_Touchpad)
var system = OpenVR.S
if (system != null)
var axisId = (uint)buttonId - (uint)EVRButtonId.k_EButton_Axis0;
system.TriggerHapticPulse(index, axisId, (char)durationMicroSec);
//扳机扣下或释放的量才可以改变状态
public float hairTriggerDelta = 0.1f; // amount trigger must be pulled or released to change state
float hairTriggerL
bool hairTriggerState, hairTriggerPrevS
/// &summary&
/// 更新扳机状态
/// &/summary&
void UpdateHairTrigger()
hairTriggerPrevState = hairTriggerS
var value = state.rAxis1.x; // trigger
if (hairTriggerState)
if (value & hairTriggerLimit - hairTriggerDelta || value &= 0.0f)
hairTriggerState =
if (value & hairTriggerLimit + hairTriggerDelta || value &= 1.0f)
hairTriggerState =
hairTriggerLimit = hairTriggerState ? Mathf.Max(hairTriggerLimit, value) : Mathf.Min(hairTriggerLimit, value);
public bool GetHairTrigger() { Update(); return hairTriggerS }
public bool GetHairTriggerDown() { Update(); return hairTriggerState && !hairTriggerPrevS }
public bool GetHairTriggerUp() { Update(); return !hairTriggerState && hairTriggerPrevS }
private static Device[]
/// &summary&
/// 输入的具体设备
/// &/summary&
/// &param name=&deviceIndex&&Device index.&/param&
public static Device Input(int deviceIndex)
if (devices == null)
devices = new Device[OpenVR.k_unMaxTrackedDeviceCount];
for (uint i = 0; i & devices.L i++)
devices[i] = new Device(i);
return devices[deviceIndex];
public static void Update()
for (int i = 0; i & OpenVR.k_unMaxTrackedDeviceC i++)
Input(i).Update();
// This helper can be used in a variety of ways.
Beware that indices may change
// as new devices are dynamically added or removed, controllers are physically
// swapped between hands, arms crossed, etc.
//这个枚举帮手用很多用法.注意索引也许会因为动态的新增或者移除而改变
//或者控制器物理上的在双手/双臂之间交换,等等
public enum DeviceRelation
// radially
Rightmost,
// distance - also see vr.hmd.GetSortedTrackedDeviceIndicesOfClass
FarthestLeft,
FarthestRight,
/// &summary&
/// 获取设备的索引
/// &/summary&
/// &returns&The device index.&/returns&
/// &param name=&relation&&Relation.&/param&
/// &param name=&deviceClass&&Device class.&/param&
/// &param name=&relativeTo&&Relative to.&/param&
public static int GetDeviceIndex(DeviceRelation relation,
ETrackedDeviceClass deviceClass = ETrackedDeviceClass.Controller,
int relativeTo = (int)OpenVR.k_unTrackedDeviceIndex_Hmd) // use -1 for absolute tracking space
var result = -1;
var invXform = ((uint)relativeTo & OpenVR.k_unMaxTrackedDeviceCount) ?
Input(relativeTo).transform.GetInverse() : SteamVR_Utils.RigidTransform.
var system = OpenVR.S
if (system == null)
var best = -float.MaxV
for (int i = 0; i & OpenVR.k_unMaxTrackedDeviceC i++)
if (i == relativeTo || system.GetTrackedDeviceClass((uint)i) != deviceClass)
var device = Input(i);
if (!device.connected)
if (relation == DeviceRelation.First)
var pos = invXform * device.transform.
if (relation == DeviceRelation.FarthestRight)
score = pos.x;
else if (relation == DeviceRelation.FarthestLeft)
score = -pos.x;
var dir = new Vector3(pos.x, 0.0f, pos.z).
var dot = Vector3.Dot(dir, Vector3.forward);
var cross = Vector3.Cross(dir, Vector3.forward);
if (relation == DeviceRelation.Leftmost)
score = (cross.y & 0.0f) ? 2.0f - dot :
score = (cross.y & 0.0f) ? 2.0f - dot :
if (score & best)
这里面讲了按钮的触发方法和震动,其实还可以通过委托来响应用户输入:
[C#] 纯文本查看 复制代码//========= Copyright 2015, Valve Corporation, All rights reserved. ===========
// Purpose: Test SteamVR_Controller support.
//=============================================================================
using UnityE
using System.Collections.G
using Valve.VR;
/// &summary&
/// 测试手柄脚本
/// &/summary&
public class SteamVR_TestController : MonoBehaviour
//手柄索引
List&int& controllerIndices = new List&int&();
/// &summary&
/// 引发设备连接事件
/// &/summary&
/// &param name=&args&&Arguments.&/param&
private void OnDeviceConnected(params object[] args)
//参数0为OpenVR系统的索引
var index = (int)args[0];
//OpenVR系统
var system = OpenVR.S
//没有获取到则返回
if (system == null || system.GetTrackedDeviceClass((uint)index) != ETrackedDeviceClass.Controller)
//参数1为是否连接
var connected = (bool)args[1];
//为真则Log连接到的手柄索引,打印其状态,并将该索引添加到手柄索引中
if (connected)
Debug.Log(string.Format(&Controller {0} connected.&, index));
PrintControllerStatus(index);
controllerIndices.Add(index);
//反之Log未连接,打印其状态,并将该索引从列表中移除
Debug.Log(string.Format(&Controller {0} disconnected.&, index));
PrintControllerStatus(index);
controllerIndices.Remove(index);
/// &summary&
/// 启用事件
/// &/summary&
void OnEnable()
//从工具事件从监听连接事件
SteamVR_Utils.Event.Listen(&device_connected&, OnDeviceConnected);
/// &summary&
/// 禁用事件
/// &/summary&
void OnDisable()
SteamVR_Utils.Event.Remove(&device_connected&, OnDeviceConnected);
/// &summary&
/// 打印手柄的状态
/// &/summary&
/// &param name=&index&&Index.索引&/param&
void PrintControllerStatus(int index)
var device = SteamVR_Controller.Input(index);
Debug.Log(&index: & + device.index);
Debug.Log(&connected: & + device.connected);
Debug.Log(&hasTracking: & + device.hasTracking);
Debug.Log(&outOfRange: & + device.outOfRange);
Debug.Log(&calibrating: & + device.calibrating);
Debug.Log(&uninitialized: & + device.uninitialized);
Debug.Log(&pos: & + device.transform.pos);
Debug.Log(&rot: & + device.transform.rot.eulerAngles);
Debug.Log(&velocity: & + device.velocity);
Debug.Log(&angularVelocity: & + device.angularVelocity);
//左右手判断
var l = SteamVR_Controller.GetDeviceIndex(SteamVR_Controller.DeviceRelation.Leftmost);
var r = SteamVR_Controller.GetDeviceIndex(SteamVR_Controller.DeviceRelation.Rightmost);
Debug.Log((l == r) ? &first& : (l == index) ? &left& : &right&);
EVRButtonId[] buttonIds = new EVRButtonId[] {
EVRButtonId.k_EButton_ApplicationMenu,
EVRButtonId.k_EButton_Grip,
EVRButtonId.k_EButton_SteamVR_Touchpad,
EVRButtonId.k_EButton_SteamVR_Trigger
//轴心id Touchpad是axis0
Trigger是axis1
EVRButtonId[] axisIds = new EVRButtonId[] {
EVRButtonId.k_EButton_SteamVR_Touchpad,
EVRButtonId.k_EButton_SteamVR_Trigger
//点和光标
public Transform point,
void Update()
//遍历索引 再一一检测
foreach (var index in controllerIndices)
var overlay = SteamVR_Overlay.
if (overlay && point && pointer)
var t = SteamVR_Controller.Input(index).
pointer.transform.localPosition = t.
pointer.transform.localRotation = t.
var results = new SteamVR_Overlay.IntersectionResults();
var hit = puteIntersection(t.pos, t.rot * Vector3.forward, ref results);
point.transform.localPosition = results.
point.transform.localRotation = Quaternion.LookRotation(results.normal);
//遍历按钮 上面只列举了菜单,紧握,触摸板,扳机四个按钮
foreach (var buttonId in buttonIds)
//按下事件
if (SteamVR_Controller.Input(index).GetPressDown(buttonId))
Debug.Log(buttonId + & press down&);
if (SteamVR_Controller.Input(index).GetPressUp(buttonId))
Debug.Log(buttonId + & press up&);
//如果松开扳机会震动
if (buttonId == EVRButtonId.k_EButton_SteamVR_Trigger)
SteamVR_Controller.Input(index).TriggerHapticPulse();
PrintControllerStatus(index);
if (SteamVR_Controller.Input(index).GetPress(buttonId))
Debug.Log(buttonId);
//遍历axisIds
foreach (var buttonId in axisIds)
if (SteamVR_Controller.Input(index).GetTouchDown(buttonId))
Debug.Log(buttonId + & touch down&);
if (SteamVR_Controller.Input(index).GetTouchUp(buttonId))
Debug.Log(buttonId + & touch up&);
if (SteamVR_Controller.Input(index).GetTouch(buttonId))
var axis = SteamVR_Controller.Input(index).GetAxis(buttonId);
Debug.Log(&axis: & + axis);
其实,讲到这里呢差不多已经把手柄的输入讲完了,后面在条件允许的情况下也许会讲关于物理交互的一些东西,因为有朋友问到手柄和场景中的物体之前的交互,这个东西呢我们已经有了很好解决方案,当然很多游戏里面都很完美的实现了!
其实插件里面的脚本是值得去大体看看的,很多东西看了之后会明了不少,至少用起来会比较顺手些,Anyway,其实掌握手柄的控制只是一个开始!
最后希望支持的朋友点下支持,评分什么的,这一次是不需要回复的,因为我还是喜欢把楼层留下来做一些有意义的探讨什么的,之前的做法有些朋友也是不太喜欢的!
每日推荐:
装B如风,常伴吾身!
7排名<font color="#FF昨日变化4主题帖子积分
在线时间66 小时
HTC开发主要是面向哪方面应用?是做体验馆吗?
每日推荐:
73520/5000排名<font color="#FF昨日变化主题帖子积分
日久生情, 积分 3520, 距离下一级还需 1480 积分
日久生情, 积分 3520, 距离下一级还需 1480 积分
蛮牛币8673
在线时间712 小时
HTC开发主要是面向哪方面应用?是做体验馆吗?
这个有很多方向,游戏/房产/教育/军师/网咖体验店/影视等等,算是百花齐放百家争鸣!
每日推荐:
装B如风,常伴吾身!
7排名<font color="#FF昨日变化4主题帖子积分
在线时间66 小时
这个有很多方向,游戏/房产/教育/军师/网咖体验店/影视等等,算是百花齐放百家争鸣! ...
价格还是偏贵,而且还是工程机,我们是做幼儿教育领域的,对我们不太适用。
每日推荐:
73520/5000排名<font color="#FF昨日变化主题帖子积分
日久生情, 积分 3520, 距离下一级还需 1480 积分
日久生情, 积分 3520, 距离下一级还需 1480 积分
蛮牛币8673
在线时间712 小时
价格还是偏贵,而且还是工程机,我们是做幼儿教育领域的,对我们不太适用。 ...
幼儿教育确实不太适合,推荐用AR!
每日推荐:
装B如风,常伴吾身!
9排名71昨日变化主题帖子积分
蛮牛币3412
在线时间948 小时
很实用,感谢分享
每日推荐:
73520/5000排名<font color="#FF昨日变化主题帖子积分
日久生情, 积分 3520, 距离下一级还需 1480 积分
日久生情, 积分 3520, 距离下一级还需 1480 积分
蛮牛币8673
在线时间712 小时
很实用,感谢分享
谢谢你的支持,如果要给俺评分的话你会给几分?
每日推荐:
装B如风,常伴吾身!
73520/5000排名<font color="#FF昨日变化主题帖子积分
日久生情, 积分 3520, 距离下一级还需 1480 积分
日久生情, 积分 3520, 距离下一级还需 1480 积分
蛮牛币8673
在线时间712 小时
很实用,感谢分享
8分收到,谢谢!
每日推荐:
装B如风,常伴吾身!
7排名<font color="#FF昨日变化5主题帖子积分
在线时间80 小时
非常详细,感谢分享,请教一下场景中手柄的模型怎么可以换成自定义的模型?
每日推荐:
73520/5000排名<font color="#FF昨日变化主题帖子积分
日久生情, 积分 3520, 距离下一级还需 1480 积分
日久生情, 积分 3520, 距离下一级还需 1480 积分
蛮牛币8673
在线时间712 小时
非常详细,感谢分享,请教一下场景中手柄的模型怎么可以换成自定义的模型? ...
只需disable默认的手柄模型Model,然后把你的模型拖进去,校正位置即可!当然,你可以先校正好位置再disable!
每日推荐:
装B如风,常伴吾身!
7排名<font color="#FF昨日变化2主题帖子积分
蛮牛币3471
在线时间1015 小时
不错哦,thelab要是开源就叼爆了
每日推荐:
3222/300排名<font color="#FF昨日变化40主题帖子积分
偶尔光临, 积分 222, 距离下一级还需 78 积分
偶尔光临, 积分 222, 距离下一级还需 78 积分
在线时间103 小时
大神哥哥 膜拜
每日推荐:
73520/5000排名<font color="#FF昨日变化主题帖子积分
日久生情, 积分 3520, 距离下一级还需 1480 积分
日久生情, 积分 3520, 距离下一级还需 1480 积分
蛮牛币8673
在线时间712 小时
大神哥哥 膜拜
^-^你这样讲会让俺自信心爆棚的!
每日推荐:
装B如风,常伴吾身!
73520/5000排名<font color="#FF昨日变化主题帖子积分
日久生情, 积分 3520, 距离下一级还需 1480 积分
日久生情, 积分 3520, 距离下一级还需 1480 积分
蛮牛币8673
在线时间712 小时
不错哦,thelab要是开源就叼爆了
是啊,那样的话估计会有很多很好的游戏从中衍生出来!实际上很多htc Vive的游戏都是从中得到的启发!
每日推荐:
装B如风,常伴吾身!
7排名<font color="#FF昨日变化2主题帖子积分
蛮牛币3471
在线时间1015 小时
是啊,那样的话估计会有很多很好的游戏从中衍生出来!实际上很多htc Vive的游戏都是从中得到的启发! ...
最近没看HTC,好头盔在我那吃灰。忙完了赶紧写点小玩意自己玩玩
每日推荐:
游戏蛮牛给予质量较高、影响力较大的unity相关技术开发者的荣誉称号
经过游戏蛮牛认证的蛮牛小翻译
连续签到30天
社区QQ达人
使用QQ帐号登录论坛的用户
认证开发者
经过游戏蛮牛认证的独立开发者

我要回帖

更多关于 excel开发工具怎么用 的文章

 

随机推荐