3D坐标系是3D游戏开发的基础概念。一般3D软件都是采用笛卡尔坐标系来描述物体的坐标信息。笛卡尔坐标系分为左手坐标系和右手坐标系:
在Unity中使用的是左手坐标系,其中X轴代表水平方向,Y轴代表垂直方向,而Z轴代表深度。
Unity有如下几种坐标系统。
1,全局坐标系(world coordinate system)
全局坐标系是用于描述场景内所有物体位置和方向的基准,也称为世界坐标系(也就是上面提到的笛卡尔左手坐标系)。
在Unity场景中创建的物体都是以全局坐标系中的坐标原点(0,0,0)来确定各自的位置。
2,局部坐标系(local coordinate system)
每个物体都有其独立的物体坐标系,并且随物体进行相同的移动或旋转,也称为模型坐标系或物体坐标系。
通过点击工具栏中的Global或Local,可以清楚的看到物体的局部坐标系与全局坐标系的不同。
如果一个物体有父物体,那么父子之间的坐标系是相互关联的,此时子物体会以父物体作为自身局部坐标系的坐标原点。
3,相机坐标系
以摄像机视角出发,观察物体的位置和方向建立的坐标系。使用此坐标系可以方便的判断物体是否在相机前方以及物体之间的先后遮挡顺序。
4,屏幕坐标系
建立在屏幕上的二维坐标系,用来描述像素在屏幕上的位置。
说道3D坐标系就必须提到Transform,Transform表示一个物体的位置、旋转、缩放等信息。
1,位置(position/localPosition)
先阐述两个最基本的概念:
transform.position
:表示该物体在全局坐标中的位置信息。transform.localPosition
:表示该物体相对于父物体的位置信息。最普通的方法Transform.Translate
,可以将自身在某个方向上移动某段距离,方向(direction)和距离(distance)由第一个参数(translation)指定。于是我们可以看到如下的代码:
public class ExampleClass : MonoBehaviour {
void Update() {
// 将自身(局部坐标系)在前方(Z轴)移动(1*一帧的持续时间)的距离
transform.Translate(Vector3.forward * Time.deltaTime);
}
}
Translate
方法还有第二个参数Space可供选择,Space表示使用的坐标空间(全局、局部),于是就会有如下代码:
public class ExampleClass : MonoBehaviour {
void Update() {
// 将自身(全局坐标系)在上方(Y轴)移动(1*一帧的持续时间)的距离
transform.Translate(Vector3.up * Time.deltaTime, Space.World);
}
}
该段代码与段代码最重要的不同在于,前者应用Translate
到局部坐标系,而后者应用Translate
到全局坐标系,源码可以清晰的表现出这段关系:
///
/// Moves the transform in the direction and distance of translation.
///
///
///
public void Translate(Vector3 translation, [DefaultValue("Space.Self")] Space relativeTo)
{
if (relativeTo == Space.World)
this.position += translation;
else
this.position += this.TransformDirection(translation);
}
// 如果没有第二个参数或参数为Space.Self,那么先将`translation`由局部坐标系转为全局坐标系,再与自身`position`相加。
// 如果第二个参数为Space.World,那么直接与自身`position`相加。
在Unity中,Transform组件的Transform.TransformPoint
方法可以将坐标点从局部坐标系转换到全局坐标系,Transform.InverseTransformPoint
可以将坐标点从全局坐标系转换到局部坐标系。而Transform.TransformDirection
和Transform.InverseTransformDirection
则用于对向量在局部坐标系和全局坐标系之间进行转换。
根据上述,下面两段代码效果是相同的:
// 先将方向从全局坐标系转换到局部坐标系,再通过Translate内部调用TransformDirection方法将方向从局部坐标系转换为全局坐标系,最后加到自身的position上。
Vector3 up = transform.InverseTransformDirection(Vector3.up);
transform.Translate(up * Time.deltaTime, Space.Self);
// 直接将translation加到自身的position上。
transform.Translate(Vector3.up * Time.deltaTime, Space.World);
Transform源码在这里。
2,旋转(rotate/localRotate)
由于和位置很类似就不赘述了。