一、Unity的坐标系体系

世界坐标系 (World Space)、屏幕坐标系 (Screen Space)、视口坐标系 (Viewport Space)、GUI界面坐标系 (GUI System)

unity中屏幕坐标转世界坐标 unity设置坐标_unity中屏幕坐标转世界坐标

左右手定则:用手握住 z 轴,大拇指朝向 z 轴正方向,然后用手的四指从 x 轴正方向握拳头,如果是左手 90 度就能把四指握到 y 轴就是左手坐标系,如果是右手 90 度握紧后到了 y 轴就是右手坐标系。 

unity中屏幕坐标转世界坐标 unity设置坐标_屏幕坐标_02

1.1、GUI 界面坐标系

在unity中创建的UI按钮,都是在GUI界面坐标系中,它的原点 (0, 0) 在最左上角,因为屏幕宽度是 Screen.width ,高度是 Screen.height ,所以 GUI 体系右下角的坐标为: (Screen.width, Screen.height) , 这是一个二维的坐标体系,坐标 z的值都为 0 。

unity中屏幕坐标转世界坐标 unity设置坐标_世界坐标系_03

1.2、视口坐标系

当使用多个摄像机,在同一个场景中显示多个视口的时候,必须要考虑视口坐标系。

一个相机对应一个视口,视口预览( Camera Preview )展示了相机所看到的所有物体,很显然,它默认大小是 (width = 1, height = 1) ,位置也是从 0 到 1 :坐标系左下角为 (0, 0) ,右上角是 (1, 1) ,一般视口坐标系主要用在相机显示中,设置Viewport Rect参数即可。

unity中屏幕坐标转世界坐标 unity设置坐标_世界坐标_04

unity中屏幕坐标转世界坐标 unity设置坐标_unity中屏幕坐标转世界坐标_05

1.3、屏幕坐标系

重点内容:

经常需要处理鼠标的相关事件(鼠标位置、单击、双击事件等),手机上的触摸反馈,这些原始数据都是屏幕坐标系相关的。

Input.mousePosition 获取的就是鼠标在屏幕中的位置坐标。屏幕坐标系中原点 (0, 0) 位于左下角,右上角是 (Screen.width, Screen.height) 

深度值z都为0。但是屏幕坐标转换成世界坐标后物体的 z 值是取决于相机的,因此: gameObject.z = camera.z 

注意:

屏幕宽高比Aspect会影响画面的显示效果。

unity中屏幕坐标转世界坐标 unity设置坐标_世界坐标系_06

1.4、 世界坐标系

重点内容:

任何情况下: transform.position 都是返回物体的世界坐标值,即使你所使用的是子物体!

另外,屏幕坐标系转换成世界坐标系的过程中,由于世界坐标系是有z值的,不能通过以下方法直接转换:

var position = Input.mousePosition;
var worldPoint = Camera.main.ScreenToWorldPoint(position);
//无z值信息

 需要知道幕布到投影仪的距离,才可以将幕布上的一个点转换到世界上来:

public Vector3 myscreenToworld(Vector3 mousepos,Transform targetTransform) 
{
        //先计算相机到目标的向量
        Vector3 dir = targetTransform.position - Camera.main.transform.position;
        //计算投影
        Vector3 normardir = Vector3.Project(dir, Camera.main.transform.forward);
        //计算是节点,需要知道处置屏幕的投影距离
        Vector3 worldpos = Camera.main.ScreenToWorldPoint(new Vector3(mousepos.x, mousepos.y, normardir.magnitude));
        return worldpos;
}

在开发过程中,经常要处理子物体的相对 transform 值,这时可以把父物体当做世界,子物体当做世界中的物体,使用这些函数,换一下坐标就和处理绝对坐标一样了。方法为:把相机放到一个产生了合适旋转角度的父物体当中!这样做的效果就是:相机就相当于子物体,父物体旋转了,子物体就不需要额外旋转了,这时候相机的局部旋转就为 0 。这在有些场景中使用起来很方便,相机已经是父物体世界中的子物体了。

计算相对坐标:

//获取的是世界坐标
var childPosition = childObject.transform.position;
//转化为父物体下的相对坐标,相当于位于父物体世界中
var relativePosition = parentObject.transform.InverseTransformPoint(childPosition);
//转化为世界坐标,注意:这里不能传入 childPosition ,因为 childPosition 就是世界坐标
var worldPosition = parentObject.transform.InverseTransformPoint(relativePosition);
//所以,下面结果是相等的!
print(childPosition == worldPosition);

 1.5、其它坐标系转换

世界坐标转屏幕坐标系:

//世界坐标转屏幕坐标系
Camera.main.WorldToScreenPoint();

//世界转视口
Camera.main.WorldToViewportPoint();

//视口转屏幕
Camera.main.ViewportToScreenPoint();
//或者
Vector2(Viewposition.x*Screen.width,Viewposition.y*Screen.hight);