当前位置:   article > 正文

VR Unity 射线点击操作_unityvr手柄射线点击

unityvr手柄射线点击

鉴于该文章点赞和收藏那么高,我推荐一款插件  VR Interaction Framework

该插件适配大部分的vr硬件,未来应该也超级兼容,而且UI事件这块兼容UGUI,单单这点就很亮眼。兼容UGUI,不用再下那么大功夫再搞按钮事件这块了。

* 我们只做VR内容时,如果要用到例如HTC手柄类的硬件的话,可能就需要一个射线点击的功能,如,点击某一个图标,按下手柄,触发点击按钮事件,那么这个类就是解决这类问题的一步
 * 射线碰撞事件的类,可以移植到大多数VR SDK上,因为每个平台都封装有了自己的注视管理,但这个引擎自身的拓展开发,方便拓展和维护,下面会有一个Debug的注释代码,可以注释掉来测试效果,如果需要有碰撞效果,必须给物体加上碰撞体,并且标签要对应,碰撞层也要对应,其实这么麻烦的原因也是为了后期的拓展开发,基础层的条件触发牢固后,上层才会安稳,舒服。

   碰撞逻辑我是放在LateUpdate里的,因为Input类放在Update里处理,解决完输入后逻辑后再处理碰撞逻辑。

  这是个抽象类,你必须新建一个类来继承他,实现获取射线的方法

  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using UnityEngine;
  5. namespace CameraFixationManager
  6. {
  7. public abstract class CameraFixationManager : MonoBehaviour
  8. {
  9. /// <summary>
  10. /// 射线是否撞到了有触发事件的碰撞体
  11. /// </summary>
  12. public static bool IsImpactCollider = false;
  13. /// <summary>
  14. /// 撞击点的位置
  15. /// </summary>
  16. public Vector3 HitPosition = Vector3.zero;
  17. /// <summary>
  18. /// 射线可以碰撞到的层
  19. /// </summary>
  20. public int RayColliderLayer = 5;
  21. #region 事件回调
  22. /// <summary>
  23. /// 射线进入回调
  24. /// </summary>
  25. public Action<GameObject> RayEnter;
  26. /// <summary>
  27. /// 射线离开的回调
  28. /// </summary>
  29. public Action<GameObject> RayLeave;
  30. /// <summary>
  31. /// 射线正在射中的回调
  32. /// </summary>
  33. public Action<GameObject> RayEntering;
  34. #endregion
  35. /// <summary>
  36. /// 响应的标签层,所有的交互事件都需要放到该层
  37. /// </summary>
  38. public string ResponseTag;
  39. /// <summary>
  40. /// 是否播放音乐特效
  41. /// </summary>
  42. public bool IsPlayAudio = true;
  43. /// <summary>
  44. /// 射线缓冲,意思就是射线当前碰撞套的物体
  45. /// </summary>
  46. private Transform _transform = null;
  47. /// <summary>
  48. /// 是否碰撞到
  49. /// </summary>
  50. protected bool IsCollider = true;
  51. protected virtual void Awake()
  52. {
  53. }
  54. /// <summary>
  55. /// 放在延迟更新是因为,输入事件一般是在Update之前,所以,处理完输入逻辑后,在 Update里判断输入状态,再在延迟更新里判断碰撞状态,这样就不用手动
  56. /// edit/ProjectSettings/ScriptExecutionOrder的编排脚本的方法执行顺序
  57. /// </summary>
  58. void LateUpdate()
  59. {
  60. if (!IsCollider) return;
  61. RaycastHit hit;
  62. //只能向屏幕中点发射线
  63. var ray = GetRay();//这里进一步抽象,因为有相机注视,还有手柄射线注视
  64. if (Physics.Raycast(ray, out hit,2000f,1<< RayColliderLayer))//这里把5层设置为可碰撞层,其他层都要忽略掉
  65. {
  66. // Debug.Log("碰撞到的物体名字是:" + hit.transform.name);
  67. HitPosition = hit.point;//碰撞点事世界位置,切记 切记
  68. if (!hit.transform.CompareTag(ResponseTag) )//如果不属于ResponseTag标签,则不进行消息触发
  69. {
  70. IsImpactCollider = false;
  71. if (_transform != null)//物体离开回调
  72. {
  73. if (RayLeave != null)
  74. RayLeave(_transform.gameObject);
  75. // Debug.Log("离开了" + _transform.name);
  76. }
  77. _transform = null;
  78. return;
  79. }
  80. IsImpactCollider = true;
  81. //被碰撞的物体第一次进入触发回调,第二个逻辑是射线从一个物体移动到另外一个物体的判断
  82. if (_transform == null || (_transform != hit.transform && _transform != null))
  83. {
  84. if (RayEnter != null)
  85. RayEnter(hit.transform.gameObject);
  86. // if (IsPlayAudio)
  87. // AudioManager.Instance.PlayAudio(AudioType.RayPass);
  88. // Debug.Log("进入了" + hit.transform.name);
  89. if(_transform!=null)
  90. {
  91. if (RayLeave != null)
  92. RayLeave(_transform.gameObject);
  93. // Debug.Log("离开了" + _transform.name);
  94. }
  95. _transform = hit.transform;
  96. }
  97. else if(_transform == hit.transform)//在进入物体的第二帧以上
  98. {
  99. if (RayEntering != null)
  100. RayEntering(hit.transform.gameObject);
  101. // Debug.Log("持续碰撞物体:" + hit.transform.name);
  102. _transform = hit.transform;
  103. }
  104. }
  105. else
  106. {
  107. IsImpactCollider = false;
  108. HitPosition = Vector3.zero;
  109. if ( _transform!= null)//物体离开回调
  110. {
  111. if (RayLeave != null)
  112. RayLeave(_transform.gameObject);
  113. // Debug.Log("离开了" + _transform.name);
  114. }
  115. _transform = null;
  116. }
  117. }
  118. protected abstract Ray GetRay();
  119. protected virtual void OnDestroy()
  120. {
  121. }
  122. }
  123. }

好了,如果你新建一个类来继承他了,我这里实现方法是

 protected override Ray GetRay()
    {
        Ray ray = new Ray(RayStartingPoint.transform.position, RayStartingPoint.transform.forward);
        return ray;
    }

RayStartingPoint为射线的发射点   这样就可以试着运行看看了,写到了这里,你会发现看不到射线,那我们这里再给你继承CameraFixationManager 的类实现一个射线显示的方法,这个射线是有宽度的,这个方法是Unity提供的接口

  1. public void OnRenderObject()
  2. {
  3. GL.PushMatrix();
  4. mat.SetPass(0);
  5. GL.Begin(GL.QUADS);
  6. GL.Color(Color.cyan);
  7. //该面片是以逆时针画线,第一个点是在物体右边开始
  8. //右边开始的第一个点
  9. Vector3 position1 = RayStartingPoint.transform.position + RayStartingPoint. transform.right * Width;
  10. //右边远方的第二个点
  11. Vector3 position2 = RayStartingPoint.transform.position;
  12. //远方没有偏移的第三个点
  13. Vector3 position3 = RayStartingPoint. transform.position;
  14. //物体的原点为第四个点
  15. Vector3 position4 = RayStartingPoint.transform.position;
  16. //设置射线
  17. Ray rayer = new Ray(RayStartingPoint.transform.position, RayStartingPoint.transform.forward);
  18. RaycastHit rayhit;
  19. //当射线与物体碰撞时,获取rayhit(rayhit.point射线与物体的接触点,rayhit.distance向量方向,rayhit.collider.gameobject获取物体的所有信息)
  20. if (Physics.Raycast(rayer, out rayhit))
  21. {
  22. //右边远方的第二个点
  23. position2 = rayhit.point + RayStartingPoint.transform.right * Width;
  24. //远方没有偏移的第三个点
  25. position3 = rayhit.point;
  26. //把球体放在射线与物体的接触点
  27. _sphere.transform.position = new Vector3(rayhit.point.x, rayhit.point.y, rayhit.point.z);
  28. }
  29. else
  30. {
  31. position2 = position1 + RayStartingPoint.transform.forward * Lenght;
  32. position3 = RayStartingPoint. transform.position + RayStartingPoint.transform.forward * Lenght;
  33. _sphere.transform.position = new Vector3(100000f, 0f, 0f);
  34. }
  35. //1
  36. GL.Vertex(position1);
  37. //2
  38. GL.Vertex(position2);
  39. //3
  40. GL.Vertex(position3);
  41. //4
  42. GL.Vertex(position4);
  43. GL.End();
  44. GL.PopMatrix();
  45. }

_sphere是一个小球体模型,作用是在碰撞点显示为一个球体,这个就需要你自己把他手动拖进去了,到了这一步,大概就把射线碰撞这块给处理好了。下一步我们处理手柄输入的问题

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/在线问答5/article/detail/792901
推荐阅读
相关标签
  

闽ICP备14008679号