坐标系,是一位叫笛卡尔的人提出的。
而后面提及的左手坐标系和右手坐标系中,在数学定义上,便使用了向量的一种运算,这种运算也是以笛卡尔命名,叫笛卡尔积。
在Unity3D中,坐标系至少存在如下三种:世界坐标系、屏幕坐标系和视口坐标系。
(当然,在世界坐标系中的坐标叫世界坐标; 屏幕坐标 和 视口坐标 定义同理,不再赘述。)
其一,世界坐标
世界坐标,是Unity3D里面每一个场景(Scene)默认的,是一个独立的初始化空间。
所以,假如一个物体的世界坐标是(0, -10, 0),可以被视为是一个“绝对坐标”。其中,虽然可以通过移动窗口或者F
键的方式把该物体移到视觉中间,但(0, -10, 0)还是(0, -10, 0),不会改变,只不过看起来在视觉中间了。
——怎么获取呢?
——使用gameObject.transform.postion
,这个值获取到的就是该物体的世界坐标。
当然,在tranform下,还有一个是localPosition
localPosition
和 position
的区别就在于:前者是相对父物体的相对世界坐标;后者是在初始化空间里的绝对世界坐标;当然,如果一个物体没有父物体,则二者等效。
其中,在Unity3D的Inspector面板中,显示的便是每一个物体的localPosition
举个例子: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
表示即可。)
——接下来的问题是:这个默认的世界坐标系是采用左手坐标系还是右手坐标系?
——答案是:左手坐标系。
此外,再插一个题外话:InverseTransformVector
和 TransformPoint
上述二者,实现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)。
但是,请注意:千万不要以为屏幕坐标是一个二维坐标!屏幕坐标,也是一个三维坐标!
——那么,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();