Unity中的坐标转换

一:Unity中的四种坐标系


——世界坐标(World Space)
世界坐标很好理解,它是一个3D坐标。就是游戏物体在你创造世界中的坐标。transfrom.position获得的是物体相对于世界坐标的位置,transfrom.localPosition获得的是物体相对于父物体坐标的位置
模型Mesh保存的顶点坐标均为局部坐标系下的坐标


——屏幕坐标(Screen Space)
屏幕坐标是以像素来定义的,与分辨率有关,例如分辨率为1280*720的屏幕则Screen.width为1280,Screen.height为720。
Screen.width = Camera.main.pixelWidth和Screen.height = Camera.main.pixelHeight只有在相机视口坐标是整个屏幕时才满足。所以不难看出Screen.width是屏幕的分辨率即屏幕的宽度, 而Camera.main.pixelWidth是相机的视口像素大小,也可以理解为相机视口的像素宽度。
屏幕的左下角坐标为(0 , 0),右上角为(Screen.width , Screen.height),z轴坐标是相机的世界坐标中z轴的负值
我们常用的Input.mousePosition和移动端的Input.GetTouch(0).position都是获得的光标在屏幕坐标的位置


——视口坐标(Viewport Space)
视口坐标系其实就是将屏幕坐标系单位化
视口坐标的左下角为(0 , 0),右上角为(1 , 1),z轴坐标是相机的世界坐标中z轴的负值
可用于制作分屏游戏

——GUI坐标
只作了解就好
它的原点在左上角为(0,0),右下角坐标为(Screen.width, Screen.height), 因为这是一个二维的坐标系,所以坐标z的值永远都为0

二:各种坐标转换


——InverseTransformPoint和TransformPoin
例如物体A的世界坐标坐标为(1,2,3),物体B的世界坐标为(2,2,2),现在需要计算物体B相对于物体A的局部坐标,则应该使用A.transform.InverseTransformPoint(B)


——屏幕坐标转世界坐标

Vector3 mousePos = Input.mousePosition;
Vector3 screenToWorld = Camera.main.ScreenToWorldPoint(new Vector3(mousePos.x, mousePos.y, -Camera.main.transform.position.z));
Debug.Log(screenToWorld);


——世界坐标转屏幕坐标

Vector3 worldToScreen = Camera.main.WorldToScreenPoint(transform.position);
Debug.Log(worldToScreen);


——屏幕坐标转视口坐标

Vector3 mousePos = Input.mousePosition;
Vector3 screenToViewport = Camera.main.ScreenToViewportPoint(mousePos);
Debug.Log(screenToViewport);


——视口坐标转屏幕坐标

Vector3 viewportToScreen = Camera.main.ViewportToScreenPoint(new Vector3(1, 1, 0));
Debug.Log(viewportToScreen);


——世界坐标转视口坐标

Vector3 worldToViewport = Camera.main.WorldToViewportPoint(transform.position);
Debug.Log(worldToViewport);


——视口坐标转世界坐标

 Vector3 viewportToWord = Camera.main.ViewportToWorldPoint(new Vector3(1, 1, -Camera.main.transform.position.z));
 Debug.Log(viewportToWord);


——屏幕坐标转UI坐标

Vector2 mousePos;
RectTransformUtility.ScreenPointToLocalPointInRectangle(transform.parent.GetComponent<RectTransform>(), Input.mousePosition, null, out mousePos);
Debug.Log(mousePos);


1.Canvas的RenderMode为Overlay时,cam参数应该为NULL

任何一个坐标转世界坐标时,z的参数都应该为相机在世界坐标中z的负值
从世界坐标转到任何一个坐标时,计算出的z值都是相机的世界坐标中z轴的负值

三:屏幕坐标转世界坐标时为什么要使用-Camera.transform.position.z

 

任何一个坐标转世界坐标时的z值,可以理解为离相机的距离。其实是把屏幕坐标投影到相机的视锥体平面上,如果z的值为0,则相当于投影到了相机的近平面上,但是近平面的最小值为0.01,所以在进行屏幕坐标转世界坐标时,屏幕坐标的z值不能为0(注意Input.mousePosition的z值为0)
而且随着z的值越来越大,投影到的平面也会越来越大,x和y的值也会越来越大

四:坐标转换的工具类

using UnityEngine;
 
/// <summary>
/// 坐标转换工具类
/// </summary>
public static class CTUtils
{
    /// <summary>
    /// 世界坐标转屏幕坐标
    /// </summary>
    public static Vector2 World2Screen(Vector3 wp, Camera camera = null)
    {
        if (camera == null)
        {
            camera = Camera.main;
        }
        return camera.WorldToScreenPoint(wp);
    }
 
    /// <summary>
    /// 屏幕坐标转世界坐标
    /// </summary>
    public static Vector3 Screen2World(Vector3 sp, Camera camera = null)
    {
        if (camera == null)
        {
            camera = Camera.main;
        }
        return camera.ScreenToWorldPoint(sp);
    }
 
    /// <summary>
    /// 世界坐标转视口坐标
    /// </summary>
    public static Vector2 World2Viewport(Vector3 wp, Camera camera = null)
    {
        if (camera == null)
        {
            camera = Camera.main;
        }
        return camera.WorldToViewportPoint(wp);
    }
 
    /// <summary>
    /// 视口坐标转世界坐标
    /// </summary>
    public static Vector3 Viewport2World(Vector3 vp, Camera camera = null)
    {
        if (camera == null)
        {
            camera = Camera.main;
        }
        return camera.ViewportToWorldPoint(vp);
    }
 
    /// <summary>
    /// 屏幕坐标转视口坐标
    /// </summary>
    public static Vector2 Screen2Viewport(Vector2 sp, Camera camera = null)
    {
        if (camera == null)
        {
            camera = Camera.main;
        }
        return camera.ScreenToViewportPoint(sp);
    }
 
    /// <summary>
    /// 视口坐标转屏幕坐标
    /// </summary>
    public static Vector2 Viewport2Screen(Vector2 vp, Camera camera = null)
    {
        if (camera == null)
        {
            camera = Camera.main;
        }
        return camera.ViewportToScreenPoint(vp);
    }
 
    /// <summary>
    /// 屏幕坐标转UI坐标
    /// </summary>
    public static Vector2 Screen2UI(Vector2 sp, RectTransform rect, Camera camera = null)
    {
        Vector2 uiLocalPos;
        RectTransformUtility.ScreenPointToLocalPointInRectangle(rect, sp, camera, out uiLocalPos);
        return uiLocalPos;
    }
 
    /// <summary>
    /// 世界坐标转UI坐标
    /// </summary>
    /// <param name="isUIObj">是否为ui物体</param>
    public static Vector2 World2UI(bool isUIObj, Vector3 wp, RectTransform rect, Camera uiCamera, Camera worldCamera = null)
    {
        if (worldCamera == null)
        {
            worldCamera = Camera.main;
        }
        Vector2 screenPos = World2Screen(wp, isUIObj ? uiCamera : worldCamera);
        return Screen2UI(screenPos, rect, uiCamera);
    }
}


转载自:https://blog.csdn.net/LLLLL__/article/details/88124564

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值