手柄震动的代码SteamVR_Controller脚本的最上面的注释里面就有说明,其实也很简单

// 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 UnityEngine;
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 = i; }public uint index { get; private set; }public bool valid { get; private set; }public bool connected { get { Update(); return pose.bDeviceIsConnected; } }public bool hasTracking { get { Update(); return pose.bPoseIsValid; } }public bool outOfRange { get { Update(); return pose.eTrackingResult == ETrackingResult.Running_OutOfRange || pose.eTrackingResult == ETrackingResult.Calibrating_OutOfRange; } }public bool calibrating { get { Update(); return pose.eTrackingResult == ETrackingResult.Calibrating_InProgress || pose.eTrackingResult == ETrackingResult.Calibrating_OutOfRange; } }public bool uninitialized { get { Update(); return pose.eTrackingResult == ETrackingResult.Uninitialized; } }// 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(); return state; }public VRControllerState_t GetPrevState() { Update(); return prevState; }public TrackedDevicePose_t GetPose() { Update(); return pose; }VRControllerState_t state, prevState;TrackedDevicePose_t pose;int prevFrameCount = -1;public void Update(){if (Time.frameCount != prevFrameCount){prevFrameCount = Time.frameCount;prevState = state;var system = OpenVR.System;if (system != null){valid = system.GetControllerStateWithPose(SteamVR_Render.instance.trackingSpace, index, ref state, ref pose);UpdateHairTrigger();}}}//长按 按下  抬起  两种参数buttonMask buttonIdpublic 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){Update();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.zero;}//上面提到的震动方法public void TriggerHapticPulse(ushort durationMicroSec = 500, EVRButtonId buttonId = EVRButtonId.k_EButton_SteamVR_Touchpad){var system = OpenVR.System;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 statefloat hairTriggerLimit;bool hairTriggerState, hairTriggerPrevState;/// <summary>/// 更新扳机状态/// </summary>void UpdateHairTrigger(){hairTriggerPrevState = hairTriggerState;var value = state.rAxis1.x; // triggerif (hairTriggerState){if (value < hairTriggerLimit - hairTriggerDelta || value <= 0.0f)hairTriggerState = false;}else{if (value > hairTriggerLimit + hairTriggerDelta || value >= 1.0f)hairTriggerState = true;}hairTriggerLimit = hairTriggerState ? Mathf.Max(hairTriggerLimit, value) : Mathf.Min(hairTriggerLimit, value);}public bool GetHairTrigger() { Update(); return hairTriggerState; }public bool GetHairTriggerDown() { Update(); return hairTriggerState && !hairTriggerPrevState; }public bool GetHairTriggerUp() { Update(); return !hairTriggerState && hairTriggerPrevState; }}private static Device[] devices;/// <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.Length; i++)devices[i] = new Device(i);}return devices[deviceIndex];}public static void Update(){for (int i = 0; i < OpenVR.k_unMaxTrackedDeviceCount; 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{First,// radially
        Leftmost,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.identity;var system = OpenVR.System;if (system == null)return result;var best = -float.MaxValue;for (int i = 0; i < OpenVR.k_unMaxTrackedDeviceCount; i++){if (i == relativeTo || system.GetTrackedDeviceClass((uint)i) != deviceClass)continue;var device = Input(i);if (!device.connected)continue;if (relation == DeviceRelation.First)return i;float score;var pos = invXform * device.transform.pos;if (relation == DeviceRelation.FarthestRight){score = pos.x;}else if (relation == DeviceRelation.FarthestLeft){score = -pos.x;}else{var dir = new Vector3(pos.x, 0.0f, pos.z).normalized;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 : dot;}else{score = (cross.y < 0.0f) ? 2.0f - dot : dot;}}if (score > best){result = i;best = score;}}return result;}
}

另外分享一个别人的关于手柄震动的教程,比较详细~~

新建yzx_controller脚本,挂在手柄上即可

一、 手柄震动一下(真的只震动一下,也许不注意都感受不到!)

using UnityEngine;
using System.Collections;public class yzx_controller : MonoBehaviour
{SteamVR_TrackedObject Hand;   SteamVR_Controller.Device device;// Use this for initializationvoid Start () {Hand = GetComponent<SteamVR_TrackedObject>();  //获得SteamVR_ TrackedObject组件
    }// Update is called once per framevoid Update () {if (Hand.isValid){//防止Start函数没加载成功,保证SteamVR_ TrackedObject组件获取成功!Hand = GetComponent<SteamVR_TrackedObject>(); }//根据index,获得手柄 device = SteamVR_Controller.Input((int)Hand.index);//如果手柄的Trigger键被按下了if (device.GetPressDown(SteamVR_Controller.ButtonMask.Trigger)) {Debug.Log("Trigger is pressed!"); //控制台输出Trigger is pressed!device.TriggerHapticPulse(500); //手柄震动函数,500代表振幅,是一个ushort类型
          }}

运行程序,扣一下Trigger键,咦,好像不对劲,都没感觉发生了什么。也许你会怀疑人生,是不是都没有捕捉到Trigger键被按下的事件?

No,No,No,明明控制台打印了Trigger is pressed !

这是为什么?……

因为,手柄只震动了一下下,你根本感觉不到。当然,你也可以修改这句代码device.TriggerHapticPulse(500); 将参数500调成1000,甚至更大(数值越大,振幅越大), 然而,震感还是太低了,因为,持续时间太短了……

二、手柄持续震动(这次,真的很有震感了……)

自然想到,如果要让手柄有震感,那么震动持续的时间一定要有保证!!!

下面的代码中,你可以随便修改代码StartCoroutine(“Shock”,0.5f) 的第二个参数(代表震动持续时间),0.5f 代表手柄持续震动0.5s,想震多久就震多久……Cool !!!

我的想法:就是通过协程去执行手柄震动,然后通过Invoke函数来决定延迟时间,即控制手柄震动的持续时间。

全面修改 yzx_controller.cs脚本,代码如下:

using UnityEngine;
using System.Collections;public class yzx_controller : MonoBehaviour
{SteamVR_TrackedObject Hand;SteamVR_Controller.Device device;bool IsShock = false;  //布尔型变量IsShock// Use this for initializationvoid Start (){Hand = GetComponent<SteamVR_TrackedObject>();  //获得SteamVR_ TrackedObject组件
    }// Update is called once per framevoid Update (){//防止Start函数没加载成功,保证SteamVR_ TrackedObject组件获取成功!if (Hand.isValid){Hand = GetComponent<SteamVR_TrackedObject>();}     device = SteamVR_Controller.Input((int)Hand.index);    //根据index,获得手柄 //如果手柄的Trigger键被按下了if (device.GetPressDown(SteamVR_Controller.ButtonMask.Trigger)){IsShock = false;  //每次按下,IsShock为false,才能保证手柄震动StartCoroutine("Shock",0.5f); //开启协程Shock(),第二个参数0.5f 即为协程Shock()的形参
        }}//定义了一个协程
IEnumerator Shock(float durationTime) {//Invoke函数,表示durationTime秒后,执行StopShock函数;Invoke("StopShock", durationTime);//协程一直使得手柄产生震动,直到布尔型变量IsShock为false;while (!IsShock){device.TriggerHapticPulse(500);yield return new WaitForEndOfFrame();}}void StopShock(){IsShock = true; //关闭手柄的震动
    }}

运行程序,Amazing!手柄真的真的震动起来了,而且可以随意调节震动的持续时间, So cool ……

转载于:https://www.cnblogs.com/unity3ds/p/5908677.html

HTC Vive开发笔记之手柄震动相关推荐

  1. unity HTC vive开发笔记二

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

  2. unity HTC vive开发笔记一

    一.首先是介绍下HTC手柄. 1.菜单按钮 这个按键没有脚本控制 就是打开个HTC的开关键 2.触控板 即是pad  可触屏 可点击 可以相当于鼠标 和 触摸屏 3.系统按钮 4.状态指示灯 5.Mi ...

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

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

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

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

  5. Unity的HTC VIVE SDK研究(手柄按键功能的研究,比较详细)

    http://blog.csdn.net/ystistheking/article/details/51553237 想交流的朋友我们可以微博互粉,我的微博黑石铸造厂厂长 ,缺粉丝啊 .....求粉求 ...

  6. HTC VIVE开发教程(一)

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

  7. HTC VIVE开发教程(五)

    前面几节我们了解了SteamVR的基本原理,现在可以进行实战开发了.但在进行VR开发前,我还要先介绍一套强大的VR开发工具--VRTK 在进行VIVE开发时,我们经常要用手柄进行一些操作,比如监听按键 ...

  8. 【VR开发】HTC Vive开发环境SteamVR配置

    文章目录 1.简介 1.1 Steam 2.2 SteamR 2.下载和安装Steam 3.注册和登陆Steam 4.下载和安装SteamVR 5.配置SteamVR 结语 1.简介 1.1 Stea ...

  9. HTC Vive 开发(二)——VRTK使用

    VRTK使用 参考文档:https://blog.csdn.net/qq_25601345/article/details/78497537?tdsourcetag=s_pcqq_aiomsg#_To ...

  10. HTC VIVE开发教程(二)

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

最新文章

  1. 浅析C# new和override的区别
  2. 在多节点集群中运行Cassandra
  3. wordpress 评论ajax,WordPress教程 WordPress实现提交评论ajax翻页效果教程
  4. 含有5亿个整数的大文件,如果排序?
  5. django 模型blank和null的区别
  6. 信息学奥赛一本通C++语言——1078:求分数序列和
  7. 基于HAProxy的网站架构
  8. KVM虚拟化常见问题
  9. c++之求数组的最大最小值及其下标
  10. 大数据如何应用于食品追溯管理
  11. 关于OMC链接LANSWITCH
  12. 苹果游戏开发教程之如何使用 SpriteKit 和 GameplayKit 制作你的街机手机游戏
  13. 斑马打印机链接数据库实现自动打印
  14. OSError解决办法
  15. java 内部类总结_java学习笔记9--内部类总结
  16. 访问者模式(Vistor Pattern)
  17. 【C Primer Plus 编程题】里程和耗油量的测量方案
  18. mysql数据库在线测试_测试面试题集-MySQL数据库灵魂拷问
  19. 将map转换成json字符串
  20. 嵌入式软件开发之------浅析linux根文件系统挂载(九)

热门文章

  1. 跳马周游c++_汉诺塔,n皇后,跳马问题汇总
  2. 服务器发电子邮件,服务器拒绝接受发件人的电子邮件地址,这封邮件无法发送...
  3. EDM模板编写踩坑指南(持续更新中)
  4. 天风掌财社新股认购如何操作?
  5. Win10 设置默认语言
  6. MetaLife Web3开放元宇宙vs内卷致命的Web2元宇宙
  7. 单片机温度传感器c语言编码,单片机中使用DS18B20温度传感器C语言程序.doc
  8. 浪潮服务器硬盘阵列怎么做,浪潮智能RAID技术为数据存储保驾护航
  9. 工业制造中的UWB定位技术
  10. 桌面图标计算机图标被禁用,电脑桌面图标常见问题