失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > Unity中使用VR手柄射线触发UI事件

Unity中使用VR手柄射线触发UI事件

时间:2022-11-08 03:30:48

相关推荐

Unity中使用VR手柄射线触发UI事件

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

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事件》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。