6. 理解3D空间与变换
2026/4/14大约 3 分钟
理解3D空间与变换
这一章是 3D 开发的核心基础。你将学会:X/Y/Z 轴是什么?局部坐标和全局坐标有什么区别?旋转为什么要用"四元数"?
3D 空间:多了一个 Z 轴
2D 游戏只有两个方向:水平(X)和垂直(Y)。3D 游戏多了一个深度方向(Z)。
在 Godot 中:
- X 轴:左右(红色箭头)
- Y 轴:上下(绿色箭头)
- Z 轴:前后(蓝色箭头)
记住颜色:RGB = XYZ(Red=X, Green=Y, Blue=Z)。
坐标系:左手系还是右手系?
Godot 使用右手坐标系(Y 轴朝上)。规则是:
- X 正方向:向右
- Y 正方向:向上
- Z 正方向:向屏幕外(朝向你)
这意味着 Z 值越大,物体离你越近。如果你想让物体"往远处走",需要减小 Z 值。
Transform3D:位置、旋转、缩放
每个 3D 节点都有一个 Transform3D 属性,包含三个部分:
1. 位置(Position)
就是物体在 3D 空间中的坐标。比如 (0, 1, 0) 表示"在原点上方 1 米处"。
C#
// C#: 设置位置
Position = new Vector3(0, 1, 0);
// C#: 移动(每帧)
Position += new Vector3(0, 0, speed * (float)delta);GDScript
# GDScript: 设置位置
position = Vector3(0, 1, 0)
# GDScript: 移动(每帧)
position += Vector3(0, 0, speed * delta)2. 旋转(Rotation)
就是物体绕哪个轴转了多少度。这里有个大坑:不要直接用欧拉角(X/Y/Z 旋转值)做复杂旋转,会出现"万向节死锁"(Gimbal Lock)问题。
什么是万向节死锁?
简单说就是:当两个旋转轴重合时,你会"丢失"一个自由度,导致旋转行为变得很奇怪。这是欧拉角的固有问题。
3. 四元数(Quaternion)
四元数是解决旋转问题的数学工具。好消息是:你不需要理解四元数的数学原理,只要知道:
- 四元数不会出现万向节死锁
- 四元数可以在两个旋转之间平滑插值(
Slerp) - Godot 里用
Quaternion类型表示
C#
// C#: 用四元数平滑旋转
var targetRotation = Quaternion.FromEuler(new Vector3(0, Mathf.Pi, 0));
Quaternion = Quaternion.Slerp(targetRotation, 0.1f);GDScript
# GDScript: 用四元数平滑旋转
var target_rotation = Quaternion.from_euler(Vector3(0, PI, 0))
quaternion = quaternion.slerp(target_rotation, 0.1)局部坐标 vs 全局坐标
每个节点都有两套坐标:
| 类型 | 说明 | 使用场景 |
|---|---|---|
| 局部坐标 | 相对于父节点的位置 | 大多数情况用这个 |
| 全局坐标 | 相对于整个世界原点的位置 | 计算世界位置时用 |
举个例子:如果角色站在一辆移动的车里,角色的"局部坐标"是相对车的位置(可能一直不变),但"全局坐标"会随着车移动而变化。
C#
// C#: 获取全局位置
Vector3 worldPos = GlobalPosition;
// C#: 获取局部位置
Vector3 localPos = Position;GDScript
# GDScript: 获取全局位置
var world_pos = global_position
# GDScript: 获取局部位置
var local_pos = position向量(Vector3)
Vector3 是 3D 开发中最常用的数据类型,表示一个有三个分量的值(X, Y, Z)。
常用操作:
C#
// C#: 向量运算
var direction = new Vector3(1, 0, 0); // 向右
var length = direction.Length(); // 长度 = 1
var normalized = direction.Normalized(); // 单位向量
var distance = a.DistanceTo(b); // 两点距离
var angle = a.AngleTo(b); // 两向量夹角GDScript
# GDScript: 向量运算
var direction = Vector3(1, 0, 0) # 向右
var length = direction.length() # 长度 = 1
var normalized = direction.normalized() # 单位向量
var distance = a.distance_to(b) # 两点距离
var angle = a.angle_to(b) # 两向量夹角本章小结
| 概念 | 一句话解释 |
|---|---|
| X/Y/Z 轴 | 左右 / 上下 / 前后 |
| Position | 物体在哪 |
| Rotation | 物体怎么转 |
| Scale | 物体多大 |
| 局部坐标 | 相对父节点 |
| 全局坐标 | 相对世界原点 |
| 四元数 | 不会出错的旋转方式 |
| Vector3 | 3D 中的"方向+距离" |
