【转载】[Unity UGUI] 屏幕坐标转换

1,404 阅读2分钟

原文链接

【Unity UGUI】屏幕坐标转换 | onelei

image.png

正文

【Unity UGUI】屏幕坐标转换

Unity 的 RectTransformUtility 函数里面提供了常用的坐标系之间的转换关系。

image.png

因为 RectTransformUtility 里面提供的函数是环形结构,所以 屏幕坐标UGUI 坐标世界坐标 三者之间可以相互转换。

由于函数都需要用到场景相机和 UGUI 相机,所以定义 两个 相机变量。

/// <summary>
/// 场景相机
/// </summary>
public static Camera ScenceCamera;

/// <summary>
/// UGUI相机
/// </summary>
public static Camera UGUICamera;

下面开始看坐标系之间的转换接口。

世界坐标->屏幕坐标

WorldToScreenPoint

/// <summary>
/// 世界坐标转屏幕坐标
/// </summary>
/// <param name="position"></param>
/// <returns></returns>
public static Vector2 WorldToScreenPoint(Vector3 worldPoint)
{
    return RectTransformUtility.WorldToScreenPoint(ScenceCamera, worldPoint);
}

/// <summary>
/// 世界坐标转屏幕坐标
/// </summary>
/// <param name="camera"></param>
/// <param name="position"></param>
/// <returns></returns>
public static Vector2 WorldToScreenPoint(Camera cam, Vector3 worldPoint)
{
    return RectTransformUtility.WorldToScreenPoint(cam, worldPoint);
}

@ShaderJoy:

注意:现在这个函数在 RectTransformUtility 中找不到了, 只找到了 Camera.WorldToScreenPoint

WorldToViewportPoint

@ShaderJoy: LayerMask_1.png

屏幕坐标->世界坐标

ScreenPointToWorldPointInRectangle

/// <summary>
/// 屏幕坐标转世界坐标
/// </summary>
/// <param name="rect"></param>
/// <param name="screenPoint"></param>
/// <param name="worldPoint"></param>
/// <returns></returns>
public static bool ScreenPointToWorldPointInRectangle(RectTransform rect, Vector2 screenPoint, out Vector3 worldPoint)
{
    return RectTransformUtility.ScreenPointToWorldPointInRectangle(rect, screenPoint, UGUICamera, out worldPoint);
}

/// <summary>
/// 屏幕坐标转世界坐标
/// </summary>
/// <param name="rect"></param>
/// <param name="screenPoint"></param>
/// <param name="cam"></param>
/// <param name="worldPoint"></param>
/// <returns></returns>
public static bool ScreenPointToWorldPointInRectangle(RectTransform rect, Vector2 screenPoint, Camera cam, out Vector3 worldPoint)
{
    return RectTransformUtility.ScreenPointToWorldPointInRectangle(rect, screenPoint, cam, out worldPoint);
}

具体案例

首先记录一下坐标,然后用 检测的 UI 坐标 减去 鼠标位置(要坐标转换一下) 会得到一个向量 然后去 乘上 扩散半径,回收的时候就是将终于开始记录的坐标赋值回去即可。

RectTransformUtility.ScreenPointToWorldPointInRectangle(
    canvas.transform as RectTransform, 
    new Vector2(Input.mousePosition.x + inputUI.rect.width / 2, 
    Input.mousePosition.y + inputUI.rect.height / 2), 
    canvas.worldCamera, 
    out pos);

 Vector2 targetPos = inputUI.anchoredPosition + 
     (i.Key.anchoredPosition - inputUI.anchoredPosition).normalized * radiateSize

屏幕坐标->UGUI坐标

ScreenPointToLocalPointInRectangle

/// <summary>
/// 屏幕坐标转某个 RectTransform 下的 localPosition 坐标
/// </summary>
/// <param name="rect"></param>
/// <param name="screenPoint"></param>
/// <param name="localPoint"></param>
/// <returns></returns>
public static bool ScreenPointToLocalPointInRectangle(RectTransform rect, Vector2 screenPoint, out Vector2 localPoint)
{
    return RectTransformUtility.ScreenPointToLocalPointInRectangle(rect, screenPoint, UGUICamera, out localPoint);
}

/// <summary>
/// 屏幕坐标转某个 RectTransform 下的 localPosition 坐标
/// </summary>
/// <param name="rect"></param>
/// <param name="screenPoint"></param>
/// <param name="cam"></param>
/// <param name="localPoint"></param>
/// <returns></returns>
public static bool ScreenPointToLocalPointInRectangle(RectTransform rect, Vector2 screenPoint, Camera cam, out Vector2 localPoint)
{
    return RectTransformUtility.ScreenPointToLocalPointInRectangle(rect, screenPoint, cam, out localPoint);
}

UGUI坐标->世界坐标

transform.position 就是 UGUI 下面的世界坐标,不用转换

UGUI坐标->屏幕坐标

UGUI坐标->世界坐标->屏幕坐标

世界坐标->UGUI坐标

世界坐标->屏幕坐标-> UGUI坐标

完整代码

TransformUtility.cs

using UnityEngine;

public class TransformUtility
{
    /// <summary>
    /// 场景相机
    /// </summary>
    public static Camera ScenceCamera;

    /// <summary>
    /// UGUI相机
    /// </summary>
    public static Camera UGUICamera;

    #region 世界坐标转屏幕坐标

    /// <summary>
    /// 世界坐标转屏幕坐标
    /// </summary>
    /// <param name="position"></param>
    /// <returns></returns>
    public static Vector2 WorldToScreenPoint(Vector3 worldPoint)
    {
        return RectTransformUtility.WorldToScreenPoint(ScenceCamera, worldPoint);
    }

    /// <summary>
    /// 世界坐标转屏幕坐标
    /// </summary>
    /// <param name="camera"></param>
    /// <param name="position"></param>
    /// <returns></returns>
    public static Vector2 WorldToScreenPoint(Camera cam, Vector3 worldPoint)
    {
        return RectTransformUtility.WorldToScreenPoint(cam, worldPoint);
    }

    #endregion

    #region 屏幕坐标转世界坐标

    /// <summary>
    /// 屏幕坐标转世界坐标
    /// </summary>
    /// <param name="rect"></param>
    /// <param name="screenPoint"></param>
    /// <param name="worldPoint"></param>
    /// <returns></returns>
    public static bool ScreenPointToWorldPointInRectangle(RectTransform rect, Vector2 screenPoint, out Vector3 worldPoint)
    {
        return RectTransformUtility.ScreenPointToWorldPointInRectangle(rect, screenPoint, UGUICamera, out worldPoint);
    }

    /// <summary>
    /// 屏幕坐标转世界坐标
    /// </summary>
    /// <param name="rect"></param>
    /// <param name="screenPoint"></param>
    /// <param name="cam"></param>
    /// <param name="worldPoint"></param>
    /// <returns></returns>
    public static bool ScreenPointToWorldPointInRectangle(RectTransform rect, Vector2 screenPoint, Camera cam, out Vector3 worldPoint)
    {
        return RectTransformUtility.ScreenPointToWorldPointInRectangle(rect, screenPoint, cam, out worldPoint);
    }

    #endregion

    #region 屏幕坐标转 UGUI 坐标
    /// <summary>
    /// 屏幕坐标转某个 RectTransform 下的 localPosition 坐标
    /// </summary>
    /// <param name="rect"></param>
    /// <param name="screenPoint"></param>
    /// <param name="localPoint"></param>
    /// <returns></returns>
    public static bool ScreenPointToLocalPointInRectangle(RectTransform rect, Vector2 screenPoint, out Vector2 localPoint)
    {
        return RectTransformUtility.ScreenPointToLocalPointInRectangle(rect, screenPoint, UGUICamera, out localPoint);
    }

    /// <summary>
    /// 屏幕坐标转某个 RectTransform 下的 localPosition 坐标
    /// </summary>
    /// <param name="rect"></param>
    /// <param name="screenPoint"></param>
    /// <param name="cam"></param>
    /// <param name="localPoint"></param>
    /// <returns></returns>
    public static bool ScreenPointToLocalPointInRectangle(RectTransform rect, Vector2 screenPoint, Camera cam, out Vector2 localPoint)
    {
        return RectTransformUtility.ScreenPointToLocalPointInRectangle(rect, screenPoint, cam, out localPoint);
    }

    #endregion
}