当前位置:   article > 正文

Unity射线以及相关点击触发事件的归纳_unity 点击事件射线检测顺序

unity 点击事件射线检测顺序


前言

例如:最近在做一些Unity的小游戏需要,需要用到射线检测和点击事件等操作,虽然都是一些很基础的东西但是也折腾了一会,主要有些细节没处理好就会导致不触发,写篇博客学习记录一下吧。


一、射线检测

  1、3D射线检测

  这个是最常用的,常用于3D游戏中通过射线检测来获取鼠标点击的位置来控制任务角色的移动、以及在射击游戏中通过射线检测来进行子弹击中检测等。这里我不细说射线检测的API解析了,关于层级以及忽略自身碰撞体等情况直接查看对应的API即可。代码如下:

        if (Input.GetMouseButtonDown(0))
        {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            RaycastHit hit;
            if (Physics.Raycast(ray, out hit))
            {
                Debug.Log("射线检测:" + hit.collider.name);
            }
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

注意:射线检测是跟碰撞体配合使用的,当我们使用3D射线检测API的时候,需要给被检测的对象加上3D碰撞体。

  2、2D射线检测

这个多用于2D游戏之中,其实和本质3D几乎一直但是在发射射线的时候由于是2D,需要忽略Z轴的影响并且在发射的时候需要将屏幕坐标转换成世界坐标。代码如下:

        if (Input.GetMouseButtonDown(0))
        {
            RaycastHit2D hit = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(Input.mousePosition), Vector2.zero, 1000);
            if (hit.collider != null)
            {
                Debug.Log("射线检测:" + hit.collider.name);
            }
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

注意:2D检测需要添加2D碰撞体,且需要进行屏幕坐标到世界坐标的转换。

二、鼠标按下事件OnMouseDown

当我们需要在点击某个物体(非UGUI)的时候,我们希望对自己本身和相关联的对象进行一系列的操作,这个时候我们就会用到这个函数,并且这个函数是自动触发的。但是必须要挂在在非UGUI的物体上。代码如下:

    private void OnMouseDown()
    {
        //这个函数的触发需要依赖碰撞体,并且这个脚本必须挂在在检测的物体上且只能在点击自己碰撞体的时候才会触发,类似于IPointClickHanlder这些接口事件触发一样
        Debug.Log("鼠标按下");
    }
  • 1
  • 2
  • 3
  • 4
  • 5

注意:这个函数是依赖于碰撞体的而且必须要挂载在非UGUI的物体上才会触发,还有对应的鼠标拖拽(OnMouseDrag())、鼠标抬起(OnMouseUp()、鼠标进入(OnMouseEnter)等等类似的函数,几乎都是一样的只是触发条件不一样。

三、UGUI常用检测接口

对于UGUI的物体,我们也经常需要对鼠标在其上面的操作状态来进行对应的操作和事件响应,这就要用到我们UGUI中的事件系统了。我们只需要继承对应的鼠标操作接口,然后在接口实现函数中进行对应的操作即可。包含有:鼠标进入(IPointerEnterHandler)、鼠标点击(IPointerClickHandler)、鼠标按下(IPointerDownHandler)等等。具体部分代码如下:

public class UGUI检测 : MonoBehaviour, IPointerClickHandler,IPointerDownHandler,IPointerEnterHandler
{
    //这些接口的检测都是基于射线检测的,在UGUI中需要勾选UI组件的Raycaset Target,否则无法触发
    public void OnPointerClick(PointerEventData eventData)
    {
        Debug.Log("鼠标点击:" + transform.name);
    }

    public void OnPointerDown(PointerEventData eventData)
    {
        Debug.Log("鼠标按下");
    }

    public void OnPointerEnter(PointerEventData eventData)
    {
         Debug.Log("鼠标进入");
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

注意:实现接口的脚本必须挂载在需要监听的UGUI物体上,并且挂载的UGUI物体的Raycast Target是需要勾选的,否则无法被检测到。这些事件的触发是基于UGUI的事件系统的,所以在使用的时候务必确保Unity项目的Hierarchy面板必须有一个物体挂载了EventSystem.

四、UGUI射线检测

有时我们也需要在UGUI中进行射线的检测来获取我们当前点击到的UGUI物体,这种方法也是基于UGUI事件系统而来的。具体实现代码如下:

    /// <summary>
    /// 通过射线检测获得点击的UI物体
    /// </summary>
    /// <param name="position">输入的点</param>
    /// <returns></returns>
    public GameObject GetFirstPickGameObject(Vector2 position)
    {
        //创建事件对象
        EventSystem eventSystem = EventSystem.current;
        PointerEventData pointerEventData = new PointerEventData(eventSystem);
        pointerEventData.position = position;

        //射线检测结果列表
        List<RaycastResult> uiRaycastResultCache = new List<RaycastResult>();
        //对UI元素进行射线检测
        eventSystem.RaycastAll(pointerEventData, uiRaycastResultCache);
        //判断结果列表的数量并且输出第一个检测到的物体
        if (uiRaycastResultCache.Count > 0)
        {
            return uiRaycastResultCache[0].gameObject;
        }
        return null;
    }
    private void Update()
    {
        //射线检测UI
        if (Input.GetMouseButtonDown(0))
        {
            GameObject go = GetFirstPickGameObject(Input.mousePosition);
            if (go)
            {
                Debug.Log("检测到点击的物体:" + go.name);
            }
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

注意:由于这种检测方法也是基于Unity中的UGUI事件系统的所以也需要勾选被检测UGUI物体的Raycast Target允许接受射线,并且在Hierarchy面板中也需要进行EventSystem组件的挂载,这个函数是可以检测到当前面板中的所有接收射线的UI的,无需挂在在特定的物体上。

五、拓展

在游戏过程中我们经常需要判断鼠标是否点击在UI上,假如点击在UI上的话我们就不需要让人物移动到我们点击的目标点了,以及我们在一些情况下需要进行UI穿透等操作,这些都需要我们检测是否点击在UI上。我们可以使用以下代码判断当前是否点击在UI上。如下:

        //检测是否点击到了UGUI物体
        if (Input.GetMouseButtonDown(0))
        {
            if (EventSystem.current.IsPointerOverGameObject())
            {
                Debug.Log("当前点击在物体上了");
            }
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

注意:这个也是基于UGUI事件系统的,需要开启接收射线(Raycast Target),并且场景中有挂载EventSystem。无需挂在在特定物体上且只检测UGUI对象。

六、总结

对于不同的情况我们可以选择自己需要的以及最方便、高效的检测方法,以上为个人学习记录,如有不对的地方希望大家指正讨论,一起学习进步。

本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号