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

Unity中GraphicRaycaster射线检测无命中问题求助

GraphicRaycaster射线检测无命中问题排查与解决

问题情况

开发游戏时尝试用GraphicRaycaster标记可拾取的UI元素或物品,但射线检测完全无命中,脚本仅输出到Debug.Log("test 2"),无任何命中日志。同时控制台出现警告:

Should not be capturing when there is a hotcontrol
UnityEngine.GUIUtility:ProcessEvent (int,intptr,bool&)

已做检查:

  • 脚本挂载在Canvas上,已关联EventSystem
  • Canvas带有GraphicRaycaster组件
  • 尝试给物品图片添加2D盒碰撞体(开启Is Trigger)
  • 给物品添加Canvas组件,但问题仍未解决

问题代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;

public class InventoryCanvasTestScript : MonoBehaviour
{
    public GraphicRaycaster m_Raycaster;
    public PointerEventData m_PointerEventData;
    public EventSystem m_EventSystem;

    // Start is called before the first frame update
    void Start()
    {
        //Fetch the Raycaster from the GameObject (the Canvas)
        m_Raycaster = GetComponent<GraphicRaycaster>();
        //Fetch the Event System from the Scene
        m_EventSystem = GetComponent<EventSystem>();
    }

    void Update()
    {
        if (InventoryManager.IsInventoryOpen == true)
        {
            //Debug.Log("test 0");

            //Check if the left Mouse button is clicked
            if (Input.GetKey(KeyCode.Mouse0))
            {
                //Debug.Log("test 1");
                //Set up the new Pointer Event
                m_PointerEventData = new PointerEventData(m_EventSystem);
                //Set the Pointer Event Position to that of the mouse position
                m_PointerEventData.position = Input.mousePosition;

                //Create a list of Raycast Results
                List<RaycastResult> results = new List<RaycastResult>();


                //Raycast using the Graphics Raycaster and mouse click position
                m_Raycaster.Raycast(m_PointerEventData, results);

                //Debug.Log("test 2");

                //For every result returned, output the name of the GameObject on the Canvas hit by the Ray
                foreach (RaycastResult result in results)
                {
                    Debug.Log("test 3");
                    Debug.Log("Hit " + result.gameObject.name);
                }
            }
        }
    }
}

解决步骤

1. 移除冗余组件

GraphicRaycaster是UI专用射线检测工具,不需要给UI元素添加2D碰撞体或额外的Canvas组件,这些会干扰检测逻辑。直接移除物品上的2D盒碰撞体和额外Canvas,只保留基础UI组件(如Image)。

2. 修正EventSystem获取逻辑

当前脚本中m_EventSystem = GetComponent<EventSystem>();错误,因为EventSystem是独立GameObject,不是Canvas的子组件。改为:

void Start()
{
    m_Raycaster = GetComponent<GraphicRaycaster>();
    m_EventSystem = FindObjectOfType<EventSystem>(); // 正确获取场景中的EventSystem
}

或者直接在Inspector面板手动拖拽EventSystem到脚本的m_EventSystem字段,更高效可靠。

3. 处理Hotcontrol警告

该警告是因为有UI控件(如InputField)正在捕获输入焦点,阻塞了射线检测。解决方法:

  • 检查场景中是否有激活的InputField等控件,暂时关闭或让其失焦后再测试
  • 在射线检测前强制释放焦点:
    if (EventSystem.current.currentSelectedGameObject != null)
    {
        EventSystem.current.SetSelectedGameObject(null);
    }
    

4. 验证UI元素交互状态

  • 确保目标UI元素(如Image)的Raycast Target属性处于勾选状态(在Inspector的UI组件面板中),这是GraphicRaycaster能检测到元素的必要条件
  • 检查UI层级,确保目标元素没有被其他开启Raycast Target的UI元素完全遮挡

5. 优化射线检测逻辑

  • 用Input.GetMouseButtonDown(0)替代Input.GetKey(KeyCode.Mouse0),避免每帧重复执行检测,只在鼠标点击瞬间触发
  • 缓存射线结果列表,减少GC开销:
    private List<RaycastResult> _cachedResults = new List<RaycastResult>();
    
    void Update()
    {
        if (InventoryManager.IsInventoryOpen && Input.GetMouseButtonDown(0))
        {
            _cachedResults.Clear();
            m_PointerEventData = new PointerEventData(m_EventSystem);
            m_PointerEventData.position = Input.mousePosition;
            m_Raycaster.Raycast(m_PointerEventData, _cachedResults);
    
            foreach (RaycastResult result in _cachedResults)
            {
                Debug.Log("Hit " + result.gameObject.name);
            }
        }
    }
    

内容的提问来源于stack exchange,提问作者Muggi-86

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 06:47:49