美文网首页unity
Steam VR2.3.2射线与UGUI交互

Steam VR2.3.2射线与UGUI交互

作者: WOTTOW | 来源:发表于2019-08-15 13:24 被阅读0次
    UGUI交互.gif

    首先我们需要了解UGUI的交互原理。从表面上看EventSystem控制UGUI的输入、处理、发布等一切UGUI交互的管理者。

    EventSysytem是继承BaseInputModule这个基类实现输入、处理、发布事件。

    BaseInputModule由此看就是一个输入模块的基类。StandaloneInputModule、TouchInputModule都是继承BaseInputModule从而现实,我们也可以继承BaseInputModule实现自定义的EventSysytem。

    BaseInputModule是获取到目标后对UI的处理。那么缺少获取目标点的功能。由此出现BaseRaycaster基类模块 ,这个基类模块一般是看不出来的。

    BaseRaycaster模块的功能就是发出射线确定目标点。PhysicsRaycaster, Physics2DRaycaster, GraphicRaycaster都是继承BaseRaycaster。

    总的来理解:EventSysytem管理者,BaseInputModule输入,BaseRaycaster射线

    这个脚本使用需要禁用StandaloneInputModule;

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.EventSystems;
    using Valve.VR;
    
    public class TestB : BaseInputModule
    {
        public Transform Root; 
        public Canvas canvas;
        public int LaserNum = 1;
    
        private Camera UICamera;
    
        public GameObject[] hitObjects;
        public GameObject[] pressedObjects;
        public PointerEventData[] pointEvents;
    
        protected override void Start()
        {
            base.Start();
            hitObjects = new GameObject[LaserNum];
            pressedObjects = new GameObject[LaserNum];
            pointEvents = new PointerEventData[LaserNum];
            CreateCamera();
        }
    
        private void CreateCamera()
        {
            // 用作反射射线
            UICamera = new GameObject("UICamera").AddComponent<Camera>();
            UICamera.transform.SetParent(Root);
            UICamera.transform.localPosition = Vector3.zero; 
            UICamera.fieldOfView = 5;                           
            UICamera.nearClipPlane = 0.01f;                     
            UICamera.stereoTargetEye = StereoTargetEyeMask.None; 
            UICamera.clearFlags = CameraClearFlags.Nothing;   
            UICamera.cullingMask = 0;                          
    
            canvas.worldCamera = UICamera;
        }
    
        public override void Process()
        {
            //清除选中的UI
            ClearSelection();
    
            bool hit = GUIRaycast(0);
    
            if (hit == false)
            {
                base.HandlePointerExitAndEnter(pointEvents[0], null);
                return;
            }
    
            //保持命中状态
            hitObjects[0] = pointEvents[0].pointerCurrentRaycast.gameObject;
            base.HandlePointerExitAndEnter(pointEvents[0], hitObjects[0]);
    
            //如果是按下
            if (IsPressDown())
            {
                pointEvents[0].pressPosition = pointEvents[0].position;
                pointEvents[0].pointerPressRaycast = pointEvents[0].pointerCurrentRaycast;
                pointEvents[0].pointerPress = null;
    
                //如果是碰撞到UI
                if (hitObjects[0] != null)
                {
                    pressedObjects[0] = hitObjects[0];
                    GameObject newPressed = ExecuteEvents.ExecuteHierarchy(pressedObjects[0], pointEvents[0], ExecuteEvents.pointerDownHandler);
                    if (newPressed == null)
                    {
                        newPressed = ExecuteEvents.ExecuteHierarchy(pressedObjects[0], pointEvents[0], ExecuteEvents.pointerClickHandler);
                        pressedObjects[0] = newPressed;
    
                    }
                    else
                    {
                        pressedObjects[0] = newPressed;
                        ExecuteEvents.Execute(newPressed, pointEvents[0], ExecuteEvents.pointerClickHandler);
                    }
    
                    if (newPressed != null)
                    {
                        pointEvents[0].pointerPress = newPressed;
                        pressedObjects[0] = newPressed;
                        Select(pressedObjects[0]);
                    }
                    pointEvents[0].pointerDrag = pressedObjects[0];
                }
            }
    
            //按下轨道
            if (IsPressUp())
            {
                //发布新闻结束活动
                if (pressedObjects[0])
                {
                    ExecuteEvents.Execute(pressedObjects[0], pointEvents[0], ExecuteEvents.pointerUpHandler);
                    pointEvents[0].rawPointerPress = null;
                    pointEvents[0].pointerPress = null;
                    pressedObjects[0] = null;
                    hitObjects[0] = null;
                }
            }
        }
    
        /// <summary>
        /// 创建GUI射线
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        private bool GUIRaycast(int index)
        {
            if (pointEvents[index] == null)
            {
                pointEvents[index] = new PointerEventData(base.eventSystem);
            }
            else
            {
                pointEvents[index].Reset();
            }
    
            // 创建一个射线点
            pointEvents[index].delta = Vector2.zero;                                          
            pointEvents[index].position = new Vector2(Screen.width / 2, Screen.height / 2);     
            pointEvents[index].scrollDelta = Vector2.zero;                                      
    
            base.eventSystem.RaycastAll(pointEvents[index], m_RaycastResultCache);
            pointEvents[index].pointerCurrentRaycast = FindFirstRaycast(m_RaycastResultCache);
            m_RaycastResultCache.Clear();
    
            return pointEvents[index].pointerCurrentRaycast.gameObject != null;
        }
    
        /// <summary>
        /// 清除选择
        /// </summary>
        public void ClearSelection()
        {
            if (base.eventSystem.currentSelectedGameObject)
            {
                base.eventSystem.SetSelectedGameObject(null);
            }
        }
    
        /// <summary>
        /// 选中
        /// </summary>
        /// <param name="go"></param>
        private void Select(GameObject go)
        {
            ClearSelection();
            if (ExecuteEvents.GetEventHandler<ISelectHandler>(go))
            {
                base.eventSystem.SetSelectedGameObject(go);
            }
        }
    
        private bool IsPressDown()
        {
            return SteamVR_Actions._default.GrabGrip.GetStateDown(SteamVR_Input_Sources.LeftHand);
        }
    
        private bool IsPressUp()
        {
            return SteamVR_Actions._default.GrabGrip.GetStateUp(SteamVR_Input_Sources.LeftHand);
        }
    }
    

    相关文章

      网友评论

        本文标题:Steam VR2.3.2射线与UGUI交互

        本文链接:https://www.haomeiwen.com/subject/dyfzjctx.html