刚开始学Unity这些坐标系确实给了我很大的困扰,总是搞不清楚哪是哪,为此出一篇研究下每个坐标系的特点和各个坐标系之间的转换,希望能给小白一点帮助:
首先我们得先确定Unity中都有什么坐标系(以下我就用自己的话说了):
1.全局坐标系:
图中方块为刚创建的一个Cube,如图,在刚开始的时候Cube的坐标系是和右上角的坐标系一样的,都属于全局坐标系(也叫世界坐标系),
对于方法transform.Position来说,他输出的数值和有没有父物体没有关系,都是输出的物体在世界上的坐标系。
2.局部坐标系:
如图,cube是在世界坐标的(0,0,0)位置,球的世界坐标是(2,0,0)但是现在可以看见,我们把Sphere设为了Cube 的父物体,现在cube的坐标变成了(-2,0,0) ,也就是说现在cube是以Sphere的坐标系为标准的,也就是说Cube在Sphere坐标系中的位置是(-2,0,0);
方法transform.localPosition输出的就是以父物体为原点的物体的坐标
上图箭头所指的就是unity世界中自带的坐标系,为左手坐标系(如果不知道左手坐标系,请看下面这个博客,也不知道这样随便搬运别人博客会咋样
https://www.cnblogs.com/aminxu/p/4441016.html
)
3.屏幕坐标系:
把屏幕看作一个坐标系,屏幕左下角是(0,0),右上角为屏幕的最大宽高(Screen.Width,Screen.High)。Z轴的坐标是相机的世界坐标中Z轴坐标的负值(这里注意:当用Input.MousePosition获取鼠标位置的时候,他的Z轴值一直为0)。
4.视口坐标系:
视口坐标系跟屏幕坐标系相似,只不过将Game视图的屏幕坐标系单位化,左下角依旧是(0,0)。右上角变为(1,1)。比较适合用比例来计算。
下面我们来说下各个坐标系之间的转换:
1.全局(世界)坐标系和局部坐标系之间的转换
1>
从局部坐标转换成世界坐标
:Transform.TransformPoint(Vector3 Pos);
2>
从世界坐标转换成局部坐标
:Transform.InverserTransformPoint(Vector3 Pos);(输出的是以物体为原点的Pos的局部坐标)
假如物体(挂载脚本的物体)的世界位置是(1,1,1),pos输入的位置为(2,3,5),那么输出的应该是一个(1,2,4)
可以求得一个物体在另一个物体的相对位置。
3>
将一个方向从全局坐标系转换到局部坐标系
:Transform.TransformDirection(Vector3 dir)
4>
将一个方向从局部坐标系转换到全局坐标系
:Transform.InverseTransformDirection(Vector3 dir)
5>同理还有对一个向量的操作,这里就不说了
这里说一下关于transform.forward 和Vector3.forward的相关知识
1>在transform.forward中,他的方向代表着物体自身的z轴的方向,但是
在Transform.Translate中比较容易搞混的一点
是,当Transform.Translate的第二个参数为world的时候,物体运动的方向是按物体的z轴方向运动的,但是当第二个参数为self的时候,物体的运动方向是根据你旋转角度判断的,就是说假如你旋转了45°,现在你物体的z轴是世界坐标中45°的方向,但是当物体运动的时候,其实是在90°的方向上运动的,可以理解为现在你的自身角度为45,在运动的时候世界坐标为了找到你自身的位置又给你偏移了45°,也就是90°了(目前我是这么理解的,如果还有比较好的理解方法请告诉我,感觉我就是在强行理解哈哈)
2>在Vector3.forward中,是跟旋转没有关系的,他代表的只是(0,0,1)这个方向。
2.屏幕坐标系和世界坐标系之间的转换
1>将屏幕坐标转换为世界坐标
:Camera.ScreenToWorldPoint(Vector3 Pos);
这里需要注意一下相机的设置,众所周知,相机的视野是一个锥形提,有一个远截面和一个近截面,如果你想转换出来的坐标希望是正确的,那么你赋值进去坐标的Z值应该在远近这个范围内,而且z越大,你转换出来坐标的x,y的范围越大,同时转换出来的z值应该是加上相机的z值的,如果你的z值不在那个范围内,那么输出的就是一个你相机的位置坐标
2>将世界坐标转换为屏幕坐标
:Camera.WorldToScreenPoint(Vector3 Pos);
这里输出的是一个屏幕坐标,是个Vector3类型,他的Z值就是相机Z值的负值。
3.屏幕坐标与视口坐标的转换
1>将屏幕坐标转换为视口坐标
:Camera.ScreenToViewportPoint(Vector3 Pos);
2>将视口坐标转换为屏幕坐标
:Camera.ViewportToScreenPoint(Vector3 Pos);
视口坐标跟屏幕坐标原理其实相似,就是把屏幕坐标单位化,和全局坐标的转化也可以参考屏幕坐标
4.全局坐标系和视口坐标系之间的转换
1>将全局坐标转换为视口坐标
:Camera.WorldToViewportPoint(Vector3 Pos);
2>将视口坐标转换为全局坐标
:Camera.ViewportToWorldPoint(Vector3 Pos);