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

Unity中如何通过RayCast检测并交互当前被射线照射的UI元素

基于GraphicRaycaster的UI射线检测实现方案

该方案无需为每个UI元素挂载额外脚本,仅依赖Unity原生组件即可完成检测与交互。

前置配置确认

  • 场景内所有Canvas默认自带GraphicRaycaster组件,无需额外添加
  • 需响应射线的UI元素保持Graphic组件(Image、Text、RawImage等)的Raycast Target属性为默认勾选状态即可

核心实现代码

首先引入必要命名空间:

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

将如下逻辑整合到你原有射线发射的脚本中即可:

// 提前缓存对应Canvas的GraphicRaycaster和EventSystem实例,避免每帧查找
private GraphicRaycaster uiRaycaster;
private EventSystem eventSystem;

private void Start()
{
    // 可根据实际需求指定对应Canvas的GraphicRaycaster,多Canvas时可分别缓存
    uiRaycaster = FindObjectOfType<GraphicRaycaster>();
    eventSystem = FindObjectOfType<EventSystem>();
}

void FixedUpdate()
{
    // ---------- 原有3D物体检测逻辑保留 ----------
    int layerMask = 1 << 8;
    layerMask = ~layerMask;
    RaycastHit hit;
    bool hit3D = Physics.Raycast(transform.position, transform.TransformDirection(Vector3.forward), out hit, Mathf.Infinity, layerMask);
    if (hit3D)
    {
        Debug.DrawRay(transform.position, transform.TransformDirection(Vector3.forward) * hit.distance, Color.yellow);
        Debug.Log("命中3D物体: " + hit.collider.gameObject.name);
    }
    else
    {
        Debug.DrawRay(transform.position, transform.TransformDirection(Vector3.forward) * 1000, Color.white);
        Debug.Log("未命中3D物体");
    }

    // ---------- 新增UI检测逻辑 ----------
    // 将当前3D射线转换为屏幕坐标点,适配UI检测的输入要求
    PointerEventData pointerData = new PointerEventData(eventSystem);
    // 此处以射线发射端前方1000米的位置转换为屏幕坐标,可根据实际需求调整
    pointerData.position = Camera.main.WorldToScreenPoint(transform.TransformPoint(Vector3.forward * 1000f));
    
    // 存储UI检测结果
    List<RaycastResult> uiHitResults = new List<RaycastResult>();
    uiRaycaster.Raycast(pointerData, uiHitResults);

    if (uiHitResults.Count > 0)
    {
        // 取第一个检测到的UI(最上层的UI)
        RaycastResult firstUI = uiHitResults[0];
        Debug.Log("命中UI元素: " + firstUI.gameObject.name);
        
        // ---------- 交互逻辑示例 ----------
        // 若命中的是按钮,直接触发点击事件,无需额外绑定
        Button hitBtn = firstUI.gameObject.GetComponent<Button>();
        if (hitBtn != null && Input.GetKeyDown(KeyCode.Mouse0))
        {
            hitBtn.onClick.Invoke();
        }
        // 也可直接获取UI上挂载的任意组件调用对应方法
    }
}

注意事项

  • 多Canvas场景下可按需求过滤不同Canvas的GraphicRaycaster,减少不必要的检测开销
  • 不需要响应射线的UI直接取消勾选Raycast Target即可,可进一步降低检测消耗
  • 若使用VR/AR设备的手柄射线,只需将pointerData的position替换为手柄射线终点对应的屏幕坐标即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 07:27:01