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

Unity中如何通过GraphicRaycaster对多个Canvas共同执行Raycast检测

多Canvas批量Raycast检测解决方案

有两种成熟的实现方式,均可覆盖所有挂载了GraphicRaycaster的Canvas检测需求:


方案1:手动遍历所有GraphicRaycaster实现批量检测

核心逻辑是主动获取场景内所有激活的GraphicRaycaster实例,逐个执行检测后汇总结果:

示例代码

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

public static class UIRaycastHelper
{
    public static List<RaycastResult> GetAllUIRaycastResults(Vector2 screenPosition)
    {
        var allResults = new List<RaycastResult>();
        // 获取场景内所有GraphicRaycaster,Unity 2020+可加第二个bool参数控制是否包含未激活对象
        var allRaycasters = Object.FindObjectsOfType<GraphicRaycaster>();
        var pointerData = new PointerEventData(EventSystem.current)
        {
            position = screenPosition
        };

        foreach (var raycaster in allRaycasters)
        {
            var singleCanvasResults = new List<RaycastResult>();
            raycaster.Raycast(pointerData, singleCanvasResults);
            allResults.AddRange(singleCanvasResults);
        }

        // 按UI层级深度排序,和Unity默认点击优先级保持一致:层级越高的元素排在列表越前面
        allResults.Sort((a, b) => b.depth.CompareTo(a.depth));
        return allResults;
    }
}

调用方式

  • PC端传Input.mousePosition作为入参即可检测鼠标位置下的所有UI
  • 移动端传Input.GetTouch(0).position即可检测手指触摸位置下的所有UI

方案2:使用EventSystem原生封装的RaycastAll接口

Unity已经内置了跨所有射线检测组件的批量检测逻辑,无需自己遍历,可直接调用:

示例代码

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

public static class UIRaycastHelper
{
    public static List<RaycastResult> GetAllRaycastResults(Vector2 screenPosition)
    {
        var pointerData = new PointerEventData(EventSystem.current)
        {
            position = screenPosition
        };
        var results = new List<RaycastResult>();
        // 原生方法会自动检测所有激活的GraphicRaycaster、PhysicsRaycaster、Physics2DRaycaster
        EventSystem.current.RaycastAll(pointerData, results);
        return results;
    }

    // 扩展方法:仅过滤UI检测结果,排除3D/2D物理碰撞体的检测结果
    public static List<RaycastResult> FilterUIOnlyResults(this List<RaycastResult> allResults)
    {
        return allResults.FindAll(res => res.gameObject.GetComponentInParent<Graphic>() != null);
    }
}

特性说明

  • 原生返回的结果已经按深度排好序,无需手动排序
  • 兼容3D、2D、UI的混合检测,按需过滤结果即可
  • 性能优于手动调用FindObjectsOfType遍历的实现

优化建议

  • 若场景内Canvas数量较多,建议初始化时缓存所有GraphicRaycaster的引用,Canvas增减时再更新缓存,避免重复执行FindObjectsOfType带来的性能消耗
  • 不需要响应触摸/点击的Canvas可以直接禁用GraphicRaycaster组件,减少不必要的检测开销
  • 注意入参的坐标必须是屏幕坐标系(左下角为原点(0,0)),不要传入UGUI局部坐标或者世界坐标

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.10 06:39:02