上一篇把点、向量、坐标系这些基础概念捋了一遍,这一篇开始真正进入“矩阵到底在变什么”。
如果说上一篇是在清理术语,这一篇更像是在补 Unity 开发里一条很关键的底层直觉:你对轴的理解一旦错了,后面看旋转、缩放和顺序就只会越看越乱。
如果只停留在“矩阵乘向量会得到一个新向量”,其实还是比较空。
更重要的问题是:
- 为什么旋转能写成矩阵?
- 为什么缩放也能写成矩阵?
- 为什么矩阵乘法顺序一换,结果就完全不同?
把这些问题弄清楚,你后面再看 Unity 里的 TRS、相机矩阵、MVP 链,就不会只是在背 API。
一、线性变换的关键特征是什么
所谓线性变换,可以先粗暴理解成两件事:
- 直线还是直线
- 原点保持不动
所以像旋转、缩放、错切,都满足这个特点。
但平移不满足,因为平移会把原点从 (0, 0) 挪走。
这也是为什么二维的 2x2 矩阵,能很好地表示旋转、缩放、错切,却不能直接表示平移。
二、缩放矩阵最好理解
如果一个二维点 (x, y),我们想让它在 x 方向放大 sx 倍,在 y 方向放大 sy 倍,那么目标结果就是:
$$
(x’, y’) = (sx \cdot x, sy \cdot y)
$$
写成矩阵就是:
$$
\begin{bmatrix}
sx & 0 \
0 & sy
\end{bmatrix}
\begin{bmatrix}
x \
y
\end{bmatrix}
\begin{bmatrix}
sx \cdot x \
sy \cdot y
\end{bmatrix}
$$
这说明矩阵并不神秘,它只是把“每个轴怎么变”写成统一形式。
当 sx = sy 时,就是等比缩放。
当 sx != sy 时,就是非等比缩放。
这个区别在 Unity 里很重要,因为非等比缩放后,很多方向、法线、碰撞和子节点表现都会开始变微妙。
三、旋转矩阵为什么长那个样子
二维旋转通常是很多人第一次觉得“公式开始抽象”的地方。
绕原点逆时针旋转角度 $\theta$ 后,结果写成矩阵是:
$$
\begin{bmatrix}
\cos\theta & -\sin\theta \
\sin\theta & \cos\theta
\end{bmatrix}
$$
如果硬背,很快就忘。
更好的记法还是上一篇提过的那条:看矩阵的列向量。
原来的 x 轴 (1, 0) 旋转后,会变成:
$$
(\cos\theta, \sin\theta)
$$
原来的 y 轴 (0, 1) 旋转后,会变成:
$$
(-\sin\theta, \cos\theta)
$$
把这两个新基向量按列摆进去,就是旋转矩阵。
这个理解方式比背公式稳得多,因为它直接告诉你:
旋转矩阵,本质上是在重定义一组新的坐标轴。
四、错切矩阵最容易在 UI 和 2D 工具里见到
错切不像旋转和缩放那么常见,但它很适合帮助理解“矩阵不一定只是转和缩”。
比如一个简单的 x 方向错切:
$$
\begin{bmatrix}
1 & k \
0 & 1
\end{bmatrix}
$$
它会让点 (x, y) 变成:
$$
(x + ky, y)
$$
也就是说,y 越大,x 被推得越多。
图形会像被侧向拉斜一样。
在 Unity 日常业务里你不一定直接手写错切矩阵,但当你处理一些自定义 UI 网格、2D 变形、特殊动效时,这种思路是会用到的。
五、矩阵乘法顺序为什么不能乱
这是工程里最容易出错的点之一。
先旋转再缩放,和先缩放再旋转,结果通常不一样。
原因很简单:
前一个变换的输出,会成为后一个变换的输入。
如果你先把物体拉宽,再去旋转,旋转的是“已经被拉宽过的局部基向量”。
如果你先旋转,再缩放,缩放发生在旋转后的轴方向上。
这两个过程不是一回事。
所以矩阵乘法虽然看起来只是把几个矩阵连乘起来,但它其实是在描述一条有先后顺序的变换流水线。
六、Unity 里最常见的误解:以为旋转永远绕世界轴发生
很多人一开始看 transform.Rotate,或者自己做插值动画时,会把“旋转”理解成一个单一动作。
但真正影响结果的是:
- 你绕的是局部轴还是世界轴
- 变换是在父节点之前还是之后
- 当前对象是否已经有缩放
只要把矩阵乘法的顺序意识带进来,就会知道:
同样叫“旋转 30 度”,放在不同变换链位置里,结果可以完全不同。
七、用一个二维例子把顺序差异看直观
假设一个点先执行:
- x 方向放大 2 倍
- 再逆时针旋转 90 度
和先:
- 逆时针旋转 90 度
- 再 x 方向放大 2 倍
结果不会一样。
因为“x 方向”这个概念,在旋转前后本来就变了。
这个例子对应到 Unity 里,就是为什么父节点缩放 + 子节点旋转,经常让人觉得“不符合直觉”。
其实不是引擎错,是你正在对一组已经变化过的坐标轴继续操作。
如果你想把这个差异在 Unity 里直接打出来,可以写一个最小实验:
1 | Vector3 point = new Vector3(1f, 0f, 0f); |
哪怕只是看两行输出,也会比背“顺序不同结果不同”这句话更有体感。
八、学到这里,应该建立什么工程直觉
这篇最重要的不是记住所有矩阵形式,而是形成下面几条直觉:
- 矩阵描述的是基向量怎么变。
- 缩放、旋转、错切都是在线性框架里重排坐标轴。
- 变换顺序不同,结果通常不同。
- 只要原点移动了,就已经不再是单纯的线性变换。
这最后一点,正好会把我们带到下一篇。
九、为什么下一步一定要学齐次坐标
你会发现,到目前为止,我们能描述很多事情,但还有一个最常见的动作没纳入统一框架:平移。
而游戏开发里,平移又偏偏是最高频的。
所以图形学里才会引入齐次坐标和 3x3、4x4 矩阵,把位移也装进一套统一表达方式里。
下一篇就专门讲这个桥是怎么搭起来的。
十、总结
如果只看公式,旋转矩阵、缩放矩阵、错切矩阵很容易越学越散。
但如果你始终盯着“坐标轴怎么变、顺序怎么串”,这些矩阵就会开始统一起来。
后面进入 Unity 的 Matrix4x4 之前,这个理解是必须有的。否则你看到 4x4 只会更晕,不会更清楚。