You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity3D技术问询:2019.4版本下如何检测鼠标是否点击UI元素?

解决Unity 2019.4中点击UI时屏蔽游戏输入的问题

我之前在Unity 2019.4 LTS项目里也碰到过一模一样的问题——旧的EventSystem.current.IsPointerOverGameObject()调用突然不好使了,点暂停按钮时游戏里的左键逻辑还是会触发,折腾了好一会儿才找到靠谱的替代方案,给你分享两个实用的方法:

方案一:用EventSystem射线检测(最通用)

这个方法是通过手动发射UI射线来判断鼠标是否命中了可交互UI元素,兼容性强,在2019.4及之后的版本都稳定可用。

你可以在InputController里封装一个检测方法,每次处理游戏输入前先调用它:

using UnityEngine;
using UnityEngine.EventSystems;

public class InputController : MonoBehaviour
{
    private bool IsPointerOverUI()
    {
        // 创建PointerEventData,模拟当前鼠标位置的交互事件
        PointerEventData eventData = new PointerEventData(EventSystem.current);
        eventData.position = Input.mousePosition;

        // 存储射线检测到的UI结果
        var results = new RaycastResult[10];
        int resultCount = EventSystem.current.RaycastAll(eventData, results);

        // 如果有命中UI元素,返回true
        return resultCount > 0;
    }

    // 你的输入处理逻辑示例
    private void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            // 先判断是否点击了UI,是则跳过游戏逻辑
            if (IsPointerOverUI())
                return;

            // 这里执行你的游戏左键点击逻辑
            Debug.Log("触发游戏内左键操作");
        }
    }
}

这个方法的好处是不需要修改任何UI元素的代码,直接在输入控制器里统一处理,适合大多数场景。

方案二:通过UI事件标记状态(更精细控制)

如果你的UI有拖拽、长按等复杂交互,或者需要更精准地控制什么时候屏蔽游戏输入,可以维护一个全局状态标记,通过UI的交互事件来更新它:

  1. 首先创建一个全局的状态管理类(或者直接在InputController里加静态变量):
public static class UIInteractionState
{
    public static bool IsInteractingWithUI { get; set; }
}
  1. 给所有可交互的UI元素(比如Button、Slider、Toggle等)添加一个小脚本,监听PointerDown和PointerUp事件:
using UnityEngine;
using UnityEngine.EventSystems;

public class UIIntractionMarker : MonoBehaviour, IPointerDownHandler, IPointerUpHandler, IPointerExitHandler
{
    public void OnPointerDown(PointerEventData eventData)
    {
        UIInteractionState.IsInteractingWithUI = true;
    }

    public void OnPointerUp(PointerEventData eventData)
    {
        UIInteractionState.IsInteractingWithUI = false;
    }

    public void OnPointerExit(PointerEventData eventData)
    {
        // 防止鼠标按住UI后移出,状态没重置
        UIInteractionState.IsInteractingWithUI = false;
    }
}
  1. 然后在InputController里判断这个状态:
private void Update()
{
    if (Input.GetMouseButtonDown(0))
    {
        if (UIInteractionState.IsInteractingWithUI)
            return;

        // 执行游戏输入逻辑
    }
}

这个方案适合需要跟踪UI交互全过程的场景,比如拖拽UI时全程屏蔽游戏输入,体验更流畅。

补充:关于旧方法失效的原因

你提到的EventSystem.current.IsPointerOverGameObject()在2019.4其实并没有完全移除,只是如果你的项目用了新的Input System(而非旧的Input Manager),直接调用无参的重载会失效,这时候需要传入鼠标的pointerId:EventSystem.current.IsPointerOverGameObject(PointerInputModule.kMouseLeftId)。不过这个方法在某些复杂UI层级下偶尔会有检测不准的问题,所以更推荐上面的两种方案。

内容的提问来源于stack exchange,提问作者Neuromante

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 07:32:49