创建射线检测,确定起点和终点

public class LineController : SingletonMono<LineController>
{//属性[HideInInspector] public Vector3 pointStartPos, pointEndPos;[HideInInspector] public Vector3 lineDirection;[HideInInspector] public float lineRealLength;public Hand hand;public float rayLength = 20.0f;public LayerMask layerMask;//private UITriggerSystem currentTarget;private IEventHandle_VR currentTarget;/// <summary>/// 当前是否有触发对象/// </summary>public bool hasTarget{get { return currentTarget != null; }}//委托public Action OnEnterEvent;public Action OnExitEvent;public Action OnClickEvent;public Action<bool> OnActiveEvent;[HideInInspector] public bool active;private bool tempLineActive;public SteamVR_Action_Boolean menuAction = SteamVR_Input.GetAction<SteamVR_Action_Boolean>("Menu");public SteamVR_Action_Boolean teleportAction = SteamVR_Input.GetAction<SteamVR_Action_Boolean>("Teleport");private IEventHandle_VR currentObj;private IEventHandle_VR pressObj;void Start(){hand = Player.instance.rightHand;}void Update(){//判断是否触发圆盘按钮,如果按下就关闭射线检测if (teleportAction.GetStateDown(hand.handType)){tempLineActive = active;SetActive(false);}else if (teleportAction.GetStateUp(hand.handType)){if (tempLineActive) SetActive(true);}//按下菜单键,呼出射线if (menuAction.GetStateDown(hand.handType)){SetActive(!active);}if (!active) return;//未开启射线检测pointStartPos = hand.transform.position;lineDirection = hand.transform.forward;Ray ray = new Ray(pointStartPos, lineDirection);if (Physics.Raycast(ray, out RaycastHit hit, rayLength, layerMask)){if (hit.transform.TryGetComponent(out IEventHandle_VR uiTriggerSystem)){pointEndPos = hit.point;lineRealLength = hit.distance;onTrigger(uiTriggerSystem);//Debug.DrawLine(pointStartPos, lineDirection * rayLength, Color.green);}else{onTrigger(null);pointEndPos = pointStartPos + (lineDirection * 10000.0f - pointStartPos).normalized * rayLength;lineRealLength = rayLength;}}else{onTrigger(null);//pointEndPos = lineDirection * rayLength * 1000.0f;//有较大的误差,还不知道怎么解决,希望大佬看到可以留言解决,暂时用下面的方法。pointEndPos = pointStartPos + (lineDirection * 10000.0f - pointStartPos).normalized * rayLength;lineRealLength = rayLength;//Debug.DrawLine(pointStartPos, lineDirection * rayLength, Color.magenta);}if (hand.grabPinchAction.GetStateDown(hand.handType)){if (currentObj == null) return;pressObj = currentObj;onClick(pressObj);pressObj.OnHandDown(hand);}if (hand.grabPinchAction.GetStateUp(hand.handType)){if (pressObj == null) return;pressObj.OnHandUp(hand);pressObj = null;}if (hand.grabPinchAction.GetState(hand.handType)){currentObj?.OnHandStay(hand);}}private void onTrigger(IEventHandle_VR target){currentObj = target;if (target == null)//离开{if (currentTarget != null){currentTarget.OnHandExit(hand);onExit(currentTarget);//Debug.Log($"离开{currentTarget}");}currentTarget = null;}else{//第一次if (currentTarget == null){target.OnHandEnter(hand);onEnter(target);//Debug.Log($"进入{target}");currentTarget = target;}else if (currentTarget != target)//第n次{currentTarget.OnHandExit(hand);target.OnHandEnter(hand);onExit(currentTarget);onEnter(target);//Debug.Log($"进入{target},离开{currentTarget}");currentTarget = target;}}}/// <summary>/// 射线进入/// </summary>private void onEnter(IEventHandle_VR target){//Debug.Log("进入");OnEnterEvent?.Invoke();}/// <summary>/// 射线进入/// </summary>private void onExit(IEventHandle_VR target){//Debug.Log("离开");OnExitEvent?.Invoke();}/// <summary>/// 手柄扣动扳机/// </summary>private void onClick(IEventHandle_VR target){//Debug.Log("手柄点击");OnClickEvent?.Invoke();}/// <summary>/// 激活或者关闭射线检测/// </summary>public void SetActive(bool _active){OnActiveEvent?.Invoke(_active);active = _active;if (!_active) onTrigger(null);//当手柄关闭射线检测}
}

绘制射线

public class LineRenderer : MonoBehaviour
{private LineController lineController;public LineRenderer line;[SerializeField] GameObject targetPoint;void Start(){lineController = GetComponent<LineController>();createLine();createTargetPoint();lineController.OnEnterEvent += onEnter;lineController.OnExitEvent += onExit;lineController.OnActiveEvent += onActive;}// Update is called once per framevoid Update(){line.SetPosition(0, lineController.pointStartPos);line.SetPosition(1, lineController.pointEndPos);targetPoint.SetActive(lineController.hasTarget);if (lineController.hasTarget){targetPoint.transform.position = lineController.pointEndPos;}}void createLine(){line = Instantiate(line);line.useWorldSpace = true;line.startWidth = 0.0035f;line.endWidth = 0.0035f;}void createTargetPoint(){targetPoint = Instantiate(targetPoint);}private void onEnter(){line.material.SetFloat("_CenterIntensity", 10.0f);}private void onExit(){line.materials[0].SetFloat("_CenterIntensity", 2.0f);}private void onActive(bool active){line.enabled = active;}
}

触发UI控件的各种状态,在手柄射线触发的时候调用

public class UIInputModule_VR : SingletonMono<UIInputModule_VR>
{private EventSystem eventSystem;private PointerEventData eventData;private GameObject currentObj;public HandTriggerType handTriggerType;void Start(){eventSystem = GetComponent<EventSystem>();eventData = new PointerEventData(eventSystem);}public void MouseEnter(GameObject obj){currentObj = obj;eventData.pointerEnter = obj;ExecuteEvents.Execute(obj, eventData, ExecuteEvents.pointerEnterHandler);}public void MouseExit(GameObject obj){currentObj = null;ExecuteEvents.Execute(eventData.pointerEnter, eventData, ExecuteEvents.pointerExitHandler);}public void MouseDown(GameObject obj){eventData.pointerPress = obj;ExecuteEvents.Execute(obj, eventData, ExecuteEvents.pointerDownHandler);if(handTriggerType == HandTriggerType.Down){ExecuteEvents.Execute(obj, eventData, ExecuteEvents.pointerClickHandler);}}public void MouseUp(GameObject obj){ExecuteEvents.Execute(eventData.pointerPress, eventData, ExecuteEvents.pointerUpHandler);ExecuteEvents.Execute(eventData.pointerPress, eventData, ExecuteEvents.deselectHandler);if (currentObj == eventData.pointerPress && handTriggerType == HandTriggerType.Up){ExecuteEvents.Execute(obj, eventData, ExecuteEvents.pointerClickHandler);}}public enum HandTriggerType{Up, Down}
}public static class UIInputModuleExtension
{public static void MouseEnter(this GameObject obj){UIInputModule_VR.Instance.MouseEnter(obj);}public static void MouseExit(this GameObject obj){UIInputModule_VR.Instance.MouseExit(obj);}public static void MouseDown(this GameObject obj){UIInputModule_VR.Instance.MouseDown(obj);}public static void MouseUp(this GameObject obj){UIInputModule_VR.Instance.MouseUp(obj);}
}

其他一些按钮相关的代码

public class UIComponent_VR : MonoBehaviour, IEventHandle_VR
{private CanvasRenderer canvasRenderer;private RectTransform rectTransform;private BoxCollider boxCollider;public bool triggerSizeEveryFrame = false;public Action OnHandEnterEvent;public Action OnHandExitEvent;public Action OnHandDownEvent;public Action OnHandStayEvent;public Action OnHandUpEvent;protected virtual void Start(){boxCollider = GetComponent<BoxCollider>();rectTransform = GetComponent<RectTransform>();canvasRenderer = GetComponent<CanvasRenderer>();boxCollider.isTrigger = true;boxCollider.size = new Vector3(rectTransform.rect.width, rectTransform.rect.height);}protected virtual void Update(){if (triggerSizeEveryFrame){boxCollider.size = new Vector3(rectTransform.rect.width, rectTransform.rect.height);}}protected virtual void LateUpdate(){transform.localPosition = new Vector3(transform.localPosition.x, transform.localPosition.y, -canvasRenderer.absoluteDepth);}public virtual void OnHandEnter(Hand hand){OnHandEnterEvent?.Invoke();}public virtual void OnHandExit(Hand hand){OnHandExitEvent?.Invoke();}public virtual void OnHandDown(Hand hand){OnHandDownEvent?.Invoke();}public virtual void OnHandStay(Hand hand){OnHandStayEvent?.Invoke();}public virtual void OnHandUp(Hand hand){OnHandUpEvent?.Invoke();}
}
public interface IEventHandle_VR
{/// <summary>/// 手柄进入触发/// </summary>public void OnHandEnter(Hand hand);/// <summary>/// 手柄离开触发/// </summary>public void OnHandExit(Hand hand);/// <summary>/// 手柄按下触发/// </summary>public void OnHandDown(Hand hand);/// <summary>/// 手柄停留触发/// </summary>public void OnHandStay(Hand hand);/// <summary>/// 手柄抬起触发/// </summary>public void OnHandUp(Hand hand);
}

Button代码

public class Button_VR : UIComponent_VR
{public override void OnHandEnter(Hand hand){base.OnHandEnter(hand);hand.TriggerHapticPulse(1000);gameObject.MouseEnter();}public override void OnHandExit(Hand hand){base.OnHandExit(hand);gameObject.MouseExit();}public override void OnHandDown(Hand hand){base.OnHandDown(hand);gameObject.MouseDown();}public override void OnHandUp(Hand hand){base.OnHandUp(hand);gameObject.MouseUp();}
}

Unity中使用VR手柄射线触发UI事件相关推荐

  1. PicoXR中手柄射线与UI的交互

    PicoXR中手柄射线与UI的交互 本文将介绍在PicoXR中如何使用手柄射线与UI进行交互 基本步骤 开发Unity XR项目必不可少的要先右键点击Hierarchy面板 XR-Room-Scale ...

  2. 为SteamVR做射线触发UI

    最近需要在SteamVR上做类似VRTK的射线和UI交互的功能.我自己开发的时候的思路是在右手手柄上加一个LineRender组件,然后从手柄的位置为起点,手柄正方向transform.forward ...

  3. Unity中减少VR晕眩症的实用技术(Yanlz+Unity+XR+VR+AR+MR+SteamVR+晕眩症+征兆冲突理论+视野+帧速+相对运动错觉+光场VR+立钻哥哥+==)

    <基于Unity与SteamVR构建虚拟世界> <基于Unity与SteamVR构建虚拟世界> 版本 作者 参与者 完成日期 备注 SteamVR_Unity_V01_1.0 ...

  4. Unity中在鼠标点击的UI地方创建预制件+在指定地方创建预制件

    目录 一.目的: 1.想知道:Unity中在鼠标点击的UI地方创建预制件 二.参考: 1.Unity中动态给button的OnClick添加代码 1.Unity 在代码中设置RectTransform ...

  5. Vue中失去焦点时所触发的事件

    Vue中失去焦点时所触发的事件 1-html.失去焦点 <input type="text" onBlur="txtblur()"> <scr ...

  6. 【Unity VR开发窍门】如何在Unity中以VR视角捕捉游戏360度全景

    [背景] 经常看到有VR游戏中玩家可以在虚拟场景中拍照的功能,所以打算做一篇系列帖子,主要介绍三个功能,第一个功能是如何在Unity VR项目中从玩家视角捕捉游戏全景,第二个功能是如何将这个捕捉到的全 ...

  7. unity3d VR手柄射线拾取,投掷,发射可拿去的物体

    using UnityEngine; /// <summary> /// 手柄射线原代码要添加好1. SteamVR_LaserPointer 2.SteamVR_TrackedContr ...

  8. 如何在Unity中制作VR全景动画

    超简单的引言 本教程介绍的是如何一个人制作出像模像样的VR全景动画.笔者没有去详细的研究过动画的制作方式,或者说根本就不了解啊,所以本文章只是门外汉的一次自嗨,请勿认真,作为一种参考即可. 一 总览 ...

  9. Unity中SteamVR2.0 手柄交互调用方式

    再次接触到HTC Vive项目时发现交互已经跟几年前的写法不一样了,而且VRTK插件也需要找对应的版本才行,否则会报错,版本已经不兼容. 这里总结下我在项目中遇到的手柄交互在Unity中的调用: 1. ...

最新文章

  1. 拦截器与filter的区别
  2. linux 父子进程的关系
  3. Asp.net中服务端控件事件是如何触发的(笔记)
  4. 前端学习(2852):简单秒杀系统学习之鼠标点击方法
  5. 简单易懂的破解脱壳从0开始
  6. 网银支付_【成果巡礼】企业网银支付功能上线 上海全市法院再添便民新举措...
  7. python colorama_Python常用模块—— Colorama模块
  8. 微信手机开发 ios android 您没有APP支付权限
  9. Nagios监控Linux主机
  10. linux系统下将php和mysql命令加入到环境变量中的方法
  11. 拼多多和酷家乐面试总结(已拿offer)
  12. windows Pagefile.sys和hiberfil.sys文件
  13. 液晶面板的表面缺陷及其检测方法
  14. 为什么要背诵新概念英语?
  15. 第一篇:关键点检测算法基础及mmpose文件夹规则
  16. 肖哥教你解决安装和运行eNSP过程中遇到的各种问题
  17. Vue引用第三方动画库animate.css
  18. 赵小楼《天道》《遥远的救世主》深度解析(81)一个不愿躺着对话的女人,应给与绝对尊严,这符合强势文化范畴
  19. 软件构造学习笔记(九)面向复用的软件构造技术
  20. 抽屉原理解释及简单举例

热门文章

  1. 基于Python实现的词典分词方法或统计分词方法
  2. 基于Springboot的超市管理系统毕业设计-附源码231443
  3. 转载:拜耳阵列(Bayer Pattern)简介
  4. 想要学习人工智能,有哪些大学专业可以选择?
  5. 超微服务器系统重装,超微 bios设置,详细教您超微主板bios怎么设置U盘启动
  6. springboot+vue3+elementui plus汽车租赁网站源码
  7. linux社区的java坦克大战,Java编程:坦克大战游戏的设计
  8. Pencil:免费的手绘风格开源原型图设计工具(转载)
  9. 北大郭炜教授《程序与算法(二)算法基础》学习笔记
  10. 最小阻力之路,系统问题分析与解决八步法