无论是2d还是3d游戏开发,图形学都是基础,解析几何的基本思想是将几何图形抽象成点的运动轨迹,从而点可以作为组成图形的基本元素,而描述一个点的位置首先需要建立合适的坐标系,再从代码层面来理解,在调用任何需要设置位置的函数,或从函数获取位置信息前,必须要明确这个函数使用哪个坐标系,有了清晰的坐标系认识,能帮助你更顺畅地理解游戏世界。
2D世界的坐标系
# 2D世界的坐标系比较好理解,以cocos2d为例,它支持如下几种坐标系:
- 屏幕坐标系:又名UI坐标系,标准屏幕坐标系使用和OpenGL不同的坐标系,原点在左上角,X轴向右,Y轴向下。
- GL坐标系:原点在左下角,X轴向右,Y轴向上。
- 世界坐标系:又名绝对坐标系,世界即指游戏世界,是游戏开发中建立的概念,我们只要知道世界坐标系和 OpenGL 坐标系方向一致,原点在屏幕左下角, x 轴向右, y 轴向上。
- 节点坐标系:又名相对坐标系,本地坐标,和 OpenGL 坐标系方向一致,每个结点都有自己的坐标系。
对于初学者来说,可能并不能完成理解以上几种坐标系的应用,我觉得可以这么理解,屏幕坐标系和GL坐标系是一种坐标系理念,而节点坐标系和世界坐标系是两种不同的应用,即两者都是用的GL坐标系的理念,只是坐标系原点不相同;另外屏幕坐标系主要应用在Touch对象中的坐标(没去细究为啥不用GL坐标系)
Unity3D的四种坐标系
# U3D使用的是左手坐标系,如下图:
世界坐标系
世界坐标是按照笛卡尔坐标系定义出来的绝对坐标系,下面的各种坐标系都建立在世界坐标的基础上。我们知道二维平面内任意一个点可以用二维坐标(x,y)来表示,如果将这个概念延伸到三维空间内,那么三维空间内任意一个点都可以用三维坐标(x,y,z)来表示。Unity3D采用的是左手坐标系。在Unity3D中我们可以使用transform.position来获取场景中一个物体的世界坐标,通常情况下编辑器中的Inspector窗口是以世界坐标来描述一个3D物体的位置的,除非当一个3D物体存在父物体的时候,它会以相对坐标来描述其位置。
屏幕坐标系
屏幕坐标是以像素来定义的,它的范围是以左下角为(0,0),右上角为(Screen.width,Screen.height)定义的这样一个矩形。屏幕坐标是一个3D坐标,Z轴是以相机的世界单位来衡量的。屏幕坐标和相机之间满足:Screen.width=Camera.pixelWidth和Screen.height=Camera.pixelHeight这两个条件。例如我们将相机正对着场景中的原点(0,0,0),相机的Z轴分量为-10,按照屏幕坐标的定义,假设屏幕为800X640的大小,则此时原点转化为屏幕坐标后应该是(400,320,10)。在Unity3D中我们可以使用WorldToScreenPoint来将一个世界坐标转换为屏幕坐标。
鼠标位置Input.mousePosition获取的是屏幕坐标。
例如场景分辨率1024x768,如果屏幕被缩小至100x100,那么点击右上角是100x100,而不是分辨率的1024x768。
视口坐标系
视口坐标是标准化后的屏幕坐标。标准化的概念我们可以引申到向量的标准化中,比如一个向量(x,y)将过标准化后可以得到一个单位向量(x’,y’)。类似地,视口坐标是以0到1间的数字来表示的,它的范围是以左下角为(0,0),右上角为(1,1)定义的这样一个矩形。视口坐标是一个3D坐标,Z轴是以相机的世界单位来衡量的。通过对比可以发现视口坐标和屏幕坐标特别的相似,所以这里大家可以对比着来学习。同样以屏幕坐标中的例子来将这里的转换,例如我们将相机正对着场景中的原点(0,0,0),相机的Z轴分量为-10,按照屏幕坐标的定义,假设屏幕为800X640的大小,则此时原点转化为视口坐标后应该是(0.5,0.5,10)。在Unity3D中我们可以使用WorldToViewportPoint来将一个世界坐标转换为视口坐标。
GUI坐标系
GUI坐标是指通过OnGUI方法绘制UI时使用的坐标。这个坐标系和屏幕坐标类似,它同样是以像素来定义的,它的范围是以左上角为(0,0),右下角为(Screen.width,Screen.height)定义的这样一个矩形,GUI坐标是一个2D坐标(绝对坐标)。我们知道使用绝对坐标来进行布局的话是没有办法做自适应的,UI自适应的一个主要观点就是不要使用绝对坐标!不要使用绝对坐标!不要使用绝对坐标!
总结
关于GUI坐标系在接下来UGUI的文章中会再详细分析,暂时抄袭如下:
uGUI的坐标本质上是特殊的屏幕坐标,uGUI的Anchor决定了该坐标系的原点,pivot决定了元素本身坐标系的原点,正是这两个属性让uGUI的坐标看起来显得扑朔迷离