RectTransformUtility.ScreenPointToLocalPointInRectangle 是 Unity 中用于坐标转换的核心方法,主要功能是将 屏幕空间坐标(如鼠标点击位置)转换为 RectTransform 局部空间的坐标。这在处理 UI 交互(如点击按钮、拖动元素)时非常关键。

先说它的缺点

  1. 函数能够对坐标进行正确的转换,必须保证锚点、轴心、缩放和Canvas渲染模式都设置正确
    1. 锚点和轴心必须是(0.5,0.5),不然计算的就不对了,其他情况下想得到正确的结果,必须自己再把偏移考虑进去
    2. 缩放函数已经考虑了,不需要另外计算
    3. Canvas渲染模式的设置如下:
      1. Screen Space - Overlay:cam 必须为 null。
      2. Screen Space - Camera 或 World Space:cam 需传入渲染 Canvas 的相机(通常是 Camera.main)。

下面给出几个图片

  1. 第一张是正确的设置

  2. 第二张和第三张是不正确的设置

🚝
RectTransformUtility.ScreenPointToLocalPointInRectangle 是 Unity 中用于坐标转换的核心方法,主要功能是将 屏幕空间坐标(如鼠标点击位置)转换为 RectTransform 局部空间的坐标。这在处理 UI 交互(如点击按钮、拖动元素)时非常关键。

核心功能

  1. 屏幕坐标 → UI 局部坐标
    将屏幕上的一个点(如鼠标位置)转换为 UI 元素(RectTransform)内部的相对坐标。

  2. 处理复杂 UI 布局
    自动考虑 UI 元素的 锚点(Anchors)轴心(Pivot)缩放Canvas 渲染模式,确保转换结果准确。

应用场景

  • 点击定位:将鼠标点击位置转换为 UI 元素内的坐标,用于拖动或选择。
  • 跟随鼠标:让 UI 元素(如tooltip)跟随鼠标移动。
  • 触摸交互:在移动设备上处理触摸位置与 UI 的关系。

参数与返回值

public static bool ScreenPointToLocalPointInRectangle(
    RectTransform rect,          // 目标 UI 元素的 RectTransform
    Vector2 screenPoint,         // 屏幕坐标点(如鼠标位置)
    Camera cam,                  // 渲染 Canvas 的相机(Overlay 模式下为 null)
    out Vector2 localPoint       // 输出的局部坐标(相对于 rect 的锚点)
);
  • 返回值:若转换成功返回 true,否则返回 false(如目标 RectTransform 不可见)。

坐标系统对比

坐标系统 原点位置 方向 单位
屏幕坐标 屏幕左下角 (0,0) X 向右,Y 向上 像素
RectTransform 局部坐标 锚点位置 X 向右,Y 向上 单位(Unity 单位,与像素可能不同)

🚍
在使用 RectTransformUtility.ScreenPointToLocalPointInRectangle 进行坐标转换时,需要注意以下关键点,以确保转换结果符合预期:

1. Canvas 渲染模式的影响

  • Screen Space - Overlay
    Canvas 直接覆盖在屏幕上,此时 worldCamera 参数必须为 null

    RectTransformUtility.ScreenPointToLocalPointInRectangle(
        rectTransform, 
        screenPoint, 
        null,  // 必须为 null
        out localPoint);
    
  • Screen Space - CameraWorld Space
    Canvas 由相机渲染,需传入渲染 Canvas 的相机(通常是 Camera.main)。

    RectTransformUtility.ScreenPointToLocalPointInRectangle(
        rectTransform, 
        screenPoint, 
        canvas.worldCamera,  // 传入渲染 Canvas 的相机
        out localPoint);
    

2. 坐标系统差异

  • 屏幕坐标
    screenPoint 通常来自 Input.mousePosition 或触摸位置(如 Touch.position),以像素为单位,原点为屏幕左下角。

  • RectTransform 局部坐标
    localPoint 是相对于目标 RectTransform锚点(Anchors)的坐标:

    • 若锚点为中心(默认),localPoint 的原点是 RectTransform 的中心点。
    • 若锚点位于角落(如左上角),localPoint 的原点是锚点位置。

3. 锚点(Anchors)与轴心(Pivot)的影响

  • 锚点决定坐标系原点
    转换后的 localPoint 以锚点为基准。例如,若锚点位于左上角,localPoint(0, 0) 对应 RectTransform 的左上角。

  • 轴心影响元素位置
    若要将子元素精确定位到点击位置,需结合轴心调整:

    childRectTransform.anchoredPosition = localPoint;  // 适用于轴心为中心的情况
    

4. 缩放与分辨率适配

  • Canvas Scaler 的影响
    若 Canvas 使用 Canvas Scaler(如 Scale With Screen Size),转换结果会自动处理缩放,无需额外计算。

  • 多分辨率适配
    转换结果在不同分辨率下可能需要调整,特别是当 UI 布局依赖于固定像素大小时。

5. 穿透检测(Raycast)的限制

  • 该方法仅计算坐标,不检查点击是否实际命中 UI 元素。若需检测点击,需配合 GraphicRaycaster
    PointerEventData eventData = new PointerEventData(eventSystem);
    eventData.position = screenPoint;
    List<RaycastResult> results = new List<RaycastResult>();
    raycaster.Raycast(eventData, results);
    

6. 3D 场景中的 UI 元素

  • 若 Canvas 位于 3D 空间(World Space 模式),需确保相机能看到目标 RectTransform,否则转换结果可能异常。

7. 常见错误案例

  • 相机错误:使用 Screen Space - Camera 模式时传入 null 相机,或使用 Overlay 模式时传入相机。
  • 锚点误解:锚点分散时(如拉伸填充父元素),localPoint 的解释会更复杂。
  • 穿透问题:转换成功但 UI 未响应点击,可能是 Raycast Target 未勾选或被其他元素遮挡。