Unity3D开发之判断鼠标是否在UI上

本文探讨了Unity中EventSystem的局限性,特别是在存在PhysicsRaycaster时,如何自定义射线检测方法以准确判断鼠标是否位于UI元素上。介绍了如何通过遍历所有GraphicRaycaster并检查射线结果来实现这一目标。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

unity给我们提供了一条api。

EventSystem.current.IsPointerOverGameObject()==true

他是利用unity的EventSystem事件系统判断射线是否射到物体上。我们查看官方文档可以看到继承BaseRaycaster的有三个组件,.PhysicsRaycaster, Physics2DRaycaster, GraphicRaycaster,所以当我们项目中只有canvas自带的GraphicRaycaster时,我们可以使用上述api判断鼠标是否在UI上。但是当我们场景camera上挂有PhysicsRaycaster,则判断完全会出现问题。我们会发现鼠标移动到含有collider的3D物体上以上API也会返回true。此时我们需要自己写一个射线检测的方法来判断是否在UI上。

我们可以将方法写在静态工具类里供全局调用。

    static List<GraphicRaycaster> graphicRays;

    private static List<GraphicRaycaster> graphicRaycasters
    {
        get
        {
            if(graphicRays == null)
            {
                graphicRays = GameObject.FindObjectsOfType<GraphicRaycaster>().ToList<GraphicRaycaster>();
            }
           
            return graphicRays;
        }
    }

    private static EventSystem eventSystem
    {
        get { return EventSystem.current; }
    }

    /// <summary>
    /// 是否在UI上
    /// </summary>
    /// <returns></returns>
    public static bool IsOnUIElement()
    {
        eventData = new PointerEventData(eventSystem);
        eventData.pressPosition = Input.mousePosition;
        eventData.position = Input.mousePosition;
        List<RaycastResult> list = new List<RaycastResult>();
        if (graphicRaycasters == null) return false;
        foreach (var graphicRaycaster in graphicRaycasters)
        {
            graphicRaycaster.Raycast(eventData, list);
            foreach (var temp in list)
            {
                if (temp.gameObject.layer.Equals(5)) return true;
            }
        }
        return false;
    }

注意这里要获取所有的canvas上的GraphicRaycaster。另外:当我们要动态生成新的canvas添加到场景时,我们要写一个方法来管理新增的canvas上绑定的GraphicRaycaster。每个canvas上的GraphicRaycaster只能检测到目录下的UI.一般出现在动态生成3D canvas情景。

/// <summary>
    /// 增加新的GraphicRaycaster
    /// </summary>
    /// <param name="item"></param>
    public void AddGraphicRaycaster(GraphicRaycaster item)
    {
        graphicRays.Add(item);
    }


    /// <summary>
    /// 移除GraphicRaycaster
    /// </summary>
    /// <param name="item"></param>
    public void RemoveGraphicRaycaster(GraphicRaycaster item)
    {
        if (graphicRays.Contains(item))
            graphicRays.Remove(item);
    }

### 如何在 Unity 中实现转盘选择功能 #### 创建项目并设置场景 为了创建一个转盘选择器,在Unity Hub中新建一个Unity工程[^1]。确保选择了适合2D或3D项目的模板,这取决于希望转盘呈现的效果。 #### 设计转盘界面 设计阶段涉及准备美术资源,包括背景图片、指针图像以及各个选项的图标。这些素材可以作为Sprite导入到Unity中,并通过UI Canvas进行布局调整。对于交互部分,则需编写相应的C#脚本来控制旋转行为和检测用户输入。 #### 编写核心逻辑代码 下面提供了一个简化版的圆周运动模拟代码片段,该示例不依赖于Unity内置的UI系统或EventTrigger组件,而是利用Update函数监听鼠标的移动情况来改变物体的角度位置: ```csharp using UnityEngine; public class SpinnerController : MonoBehaviour { private float angle; void Update() { if (Input.GetMouseButton(0)) { Vector3 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition); Vector3 diff = transform.position - mousePos; // 计算角度变化量 angle += Mathf.Atan2(diff.y, diff.x) * Mathf.Rad2Deg; transform.rotation = Quaternion.Euler(new Vector3(0, 0, angle)); } } } ``` 此段代码实现了当玩家按住左键拖动时,对象会跟随鼠标方向转动的功能[^2]。然而实际应用中的转盘还需要考虑更多细节,比如停止条件判断、奖励分配机制等。 #### 添加额外特性 为了让游戏体验更加完善,还可以加入一些附加效果,例如: - **惯性滑动**:松开按钮后继续缓慢减速直到停下; - **碰撞反馈**:每当碰到特定区域时播放声音提示音效; - **视觉特效**:每次选中不同项时显示动画光晕或其他形式的变化; 以上就是构建基本转盘选择系统的指南概览。当然具体实施过程中可能还会遇到其他挑战,建议参考官方文档获取更深入的帮助和支持。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值