坐标系,是一位叫笛卡尔的人提出的。

而后面提及的左手坐标系右手坐标系中,在数学定义上,便使用了向量的一种运算,这种运算也是以笛卡尔命名,叫笛卡尔积


在Unity3D中,坐标系至少存在如下三种:世界坐标系屏幕坐标系视口坐标系

(当然,在世界坐标系中的坐标叫世界坐标屏幕坐标视口坐标 定义同理,不再赘述。)


其一,世界坐标


世界坐标,是Unity3D里面每一个场景(Scene)默认的,是一个独立的初始化空间。

所以,假如一个物体的世界坐标是(0, -10, 0),可以被视为是一个“绝对坐标”。其中,虽然可以通过移动窗口或者F键的方式把该物体移到视觉中间,但(0, -10, 0)还是(0, -10, 0),不会改变,只不过看起来在视觉中间了。


——怎么获取呢?

——使用gameObject.transform.postion,这个值获取到的就是该物体的世界坐标。


当然,在tranform下,还有一个是localPositionlocalPositionposition 的区别就在于:前者是相对父物体的相对世界坐标;后者是在初始化空间里的绝对世界坐标;当然,如果一个物体没有父物体,则二者等效


其中,在Unity3D的Inspector面板中,显示的便是每一个物体的localPosition

3857 转unity世界坐标系 u3d世界坐标_坐标系


举个例子:ParentGameObject 没有父物体,而ParentGameObject 的世界坐标是 (0, -10, 0),其下的ChildGameObject 相对世界坐标是(0, 10, 0);于是,按照上述说法:


对于ParentGameObject而言:

ParentGameObject.tranform.position = (0, -10, 0);

同时,它没有父物体,localPosition与position等价,所以,ParentGameObject.tranform.localPosition = (0, -10, 0);

对于ChildGameObject而言:

ChildGameObject.tranform.localPosition = (0, 10, 0) 自然不用多说;

重要的是,此时,ChildGameObject.tranform.position 应该等于(0, 0, 0)。

(注:在Unity3D里面,(0, 0, 0) 用Vector3.Zero表示即可。)


——接下来的问题是:这个默认的世界坐标系是采用左手坐标系还是右手坐标系?

——答案是:左手坐标系

3857 转unity世界坐标系 u3d世界坐标_3857 转unity世界坐标系_02


此外,再插一个题外话:InverseTransformVectorTransformPoint上述二者,实现localPosition 和postion

比如:

#1 : 求A物体下相对世界坐标为(10, 10, 10)的物体,其绝对世界坐标是多少?

A.tranform.TransformPoint(new Vector3(10, 10, 10));

#2 : 求绝对世界坐标为(20, -20, 20)的物体,相对于A物体的相对世界坐标是多少?

A.tranform.InverseTransformVector(new Vector3(20, -20, 20));


其二,屏幕坐标


屏幕坐标,是在Unity3D里面 Game视图下的坐标,此时,屏幕大小也需要纳入考虑。

其中,以左下角为起点(0,0),右上角为终点(Screen.width,Screen.height)

3857 转unity世界坐标系 u3d世界坐标_屏幕坐标_03


但是,请注意:千万不要以为屏幕坐标是一个二维坐标!屏幕坐标,也是一个三维坐标!


——那么,z轴坐标值怎么算?

——根据Camera的位置来算。

比如,Camera的世界坐标是(0, 0, -10),那么屏幕坐标中任何一点的z轴坐标值都是10(当然,x轴、y轴坐标值另当别论);换句话说,屏幕坐标的z轴坐标值就是camera位置的z值的相反数


于是,根据上述所说,屏幕坐标跟两个因素有关:屏幕大小和Camera的世界坐标。所以,举个例子:Camera的世界坐标是(0, 0, -10),屏幕大小为800x600,那么,屏幕里中间点的屏幕坐标是多少?是(400, 600, 10)。


当然,在Unity3D中不需要人为计算,使用方法WorldToScreenPoint() 即可把一个物体的世界坐标转换成屏幕坐标Camera.main.WorldToScreenPoint(GameObject.tranform.position);


其三,视口坐标


关于,视口坐标,其实一句话便可以讲清楚:视口坐标是标准化后的屏幕坐标。


也就是说,它和屏幕坐标的属性是一样的。只不过其范围是,左下角为起点(0,0),右上角为终点(1, 1)。其余,与屏幕坐标同理。


比如:Camera的世界坐标是(0, 0, -10),屏幕大小为800x600,那么,屏幕里中间点的视口坐标是多少?是(0.5, 0.5, 10)。


当然,在Unity3D中也不需要人为计算,使用方法WorldToViewportPoint() 即可把一个物体的世界坐标转换成视口坐标Camera.main.WorldToViewportPoint(GameObject.tranform.position);


总结:相互转换
1. 同样是世界坐标
相对世界坐标转绝对世界坐标:TransformPoint();
绝对世界坐标转相对世界坐标:InverseTransformVector();2. 世界坐标转换为屏幕坐标:Camera.main.WorldToScreenPoint();
3. 屏幕坐标转换为世界坐标:Camera.main.ScreenToWorldPoint();
4. 世界坐标转换为视口坐标::Camera.main.WorldToViewportPoint();
5. 视口坐标转换为世界坐标:Camera.main.ViewportToWorldPoint();
6. 视口坐标转换为屏幕坐标:Camera.main.ViewportToScreenPoint();
7. 屏幕坐标转换为视口坐标:Camera.main.ScreenToViewportPoint();