Unity UGUI交互(新思路)

Posted 带酒书生

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity UGUI交互(新思路)相关的知识,希望对你有一定的参考价值。

这两天在问答上碰到一个题主提了一个问题:大致想实现的是给定一个位置,然后交互该位置下的UI,起初我理解错了,后来又一想,很自然的就想到了射线+碰撞体这一套。打开编辑器后,又转念一想,这样搞的话不仅要改变画布的RenderMode,还要给所有要交互的UI搞个碰撞体,好像有点麻烦。UGUI不是一套自己的射线检测吗,可以尝试一下。
然后第一版就写出了这个

 void Start()
    
        mPointer = transform.GetComponent<RectTransform>();
        eventSystem = EventSystem.current;
        pointerEventData = new PointerEventData(eventSystem);
    
    // Update is called once per frame
    void Update()
    
        PointerSimulation();
    
    void PointerSimulation()
    
        pointerEventData.position = mPointer.anchoredPosition;
        eventSystem.RaycastAll(pointerEventData, uiRaycastResultCache);
        Debug.Log($"uiRaycastResultCache.Count");
    

运行测试一下,发现debug一直是0,想了一下,pointerEventData.position一般我们都是用的Input.MousePosition,而鼠标用的屏幕空间坐标系是以屏幕左下角为(0,0)点的,于是修改一下用来模拟鼠标的UI的相对布局就好了。

这里给新手提一下啊,你要用UGUI那套检测的话请确保你的画布上有Graphic Raycaster组件、UI上面的raycast target是开启状态。


能检测到后下一步就是跟UI交互了,脑子里第一个反应就是要交互的UI上给他挂个Item小脚本,然后管理类获取所有Item执行event等等,然后很快就否掉了,感觉还是麻烦。最后查了一下,学到了一个新的API:ExecuteEvents.Execute
它可以将PointerEventData传递给指定的物体然后触发传递的指定UI事件类型,于是,第二版脚本如下

    void PointerSimulation()
    
        pointerEventData.position = mPointer.anchoredPosition;
        eventSystem.RaycastAll(pointerEventData, uiRaycastResultCache);
        Debug.Log($"uiRaycastResultCache.Count");
        if (uiRaycastResultCache.Count > 0)
        
            for (int i = 0; i < uiRaycastResultCache.Count; i++)
            
                eventSystem.SetSelectedGameObject(uiRaycastResultCache[i].gameObject);
                ExecuteEvents.Execute(uiRaycastResultCache[i].gameObject, pointerEventData, ExecuteEvents.pointerClickHandler);
            
        
    

当UI射线检测到UI后,存储在list中,然后遍历list,将射中物体设为选中状态,然后模拟触发一下鼠标点击。当然我们还可以做更多事情,比如:

 void Drag()
    
        pointerEventData.position = Input.mousePosition;
        //射线检测ui
        eventSystem.RaycastAll(pointerEventData, uiRaycastResultCache);
        Debug.Log($"uiRaycastResultCache.Count");
        if (uiRaycastResultCache.Count > 0)
        
                eventSystem.SetSelectedGameObject(uiRaycastResultCache[0].gameObject);
                if (Input.GetMouseButtonDown(0))
                
                    ExecuteEvents.Execute(uiRaycastResultCache[0].gameObject, pointerEventData, ExecuteEvents.pointerDownHandler);

                
                if (Input.GetMouseButton(0))
                
                    ExecuteEvents.Execute(uiRaycastResultCache[0].gameObject, pointerEventData, ExecuteEvents.dragHandler);
                
                if(Input.GetMouseButtonUp(0))
                
                    ExecuteEvents.Execute(uiRaycastResultCache[0].gameObject, pointerEventData, ExecuteEvents.pointerUpHandler);

                
    
        
    

你可以把你UI里面涉及到的所有时间类型都写一遍,没有用到也不会报错哦。我这里就简单写了一个按钮触发的和UI拖拽的(UI拖拽需自己再写拖拽具体逻辑的脚本,我就不放了)

以上是关于Unity UGUI交互(新思路)的主要内容,如果未能解决你的问题,请参考以下文章

unity 射线检测,鼠标点击3D物体交互

unity UGUI为啥在父物体绑定拖拽脚本,子物体也能拖拽?

UGUI Raycaster

Unity笔记给UGUI元素添加交互性

unity中计算ugui中Text控件的所需长度

关于Unity中鼠标选取物体的解决方案