2026/1/8 3:39:09
网站建设
项目流程
服务类型的网站怎么做,网站建设培训中心,制作推广网站,北京网络安全公司有哪些文章摘要坐标变换在不同“参考系”里看同一个点/物体。
具体干的三件事#xff1a;
平移#xff1a;整体挪个位置#xff1b;旋转#xff1a;整体转个角度#xff1b;缩放#xff1a;整体放大缩小。
在数学里#xff0c;这是解析几何 线性代数的核心#xff1b;
在游戏…文章摘要坐标变换在不同“参考系”里看同一个点/物体。具体干的三件事平移整体挪个位置旋转整体转个角度缩放整体放大缩小。在数学里这是解析几何 线性代数的核心在游戏里Unity / UE / 自研引擎你看到的一切移动、转身、镜头、骨骼动画、相机跟随背后都是无数次“坐标变换”的组合。下面我用大白话 具体游戏例子把这件事从直觉讲到公式再讲到代码和实际用法。一、先弄清楚为啥要“坐标变换”1.1 同一个东西在不同“参考系”里坐标是不一样的想象一个简单场景你站在房间中间房间在地图上的位置也有个坐标摄像机在天花板上看你小地图也在俯视整个房间。问题来了“你这个人”到底坐标是多少要看是谁在说以“整个地图”为参考你的位置是“世界坐标”例如 (100, 0, 50)以“房间”为参考你的位置也可以写成“相对于这个房间”的局部坐标例如 (3, 0, 2)以“你自己”为参考你的手、脚的位置是“相对于你的身体”的局部坐标比如手在 (0.5, 1.2, 0)。同一个点在不同坐标系下的坐标值是不一样的。坐标变换干的就是在这些坐标系之间“翻译”。1.2 游戏里的典型场景父子节点 世界坐标在 Unity 里一个 GameObject 有 transformlocalPosition / localRotation / localScale相对父物体position / rotation / lossyScale世界坐标下。你经常会做的事把一个武器挂在角色手上武器坐标相对手骨骼再把角色放到世界任意一个位置角色坐标相对世界角色再旋转、移动武器会自然跟着走、跟着转这背后就是父子层级的坐标变换子物体坐标 在父坐标系下的局部坐标要渲染、做物理时必须把这些局部坐标转换成世界坐标。二、三大基本操作平移、旋转、缩放用生活话说一遍2.1 平移整体搬家平移 整体挪个位置不改变方向和大小。类比一下你把一张画从桌子上拿到地上画上的所有点的位置都变了但图案形状没变。数学上原点 P(x, y, z)平移向量 T(tx, ty, tz)平移后的点 P’ P T。Unity 里transform.positionnewVector3(1,0,0);// 向世界 x 方向平移 1这就是一次最直观的坐标变换加一个向量。2.2 旋转绕某个点/轴转一圈旋转 改变方向但不改变长度。生活里你手里拿着一支笔笔尖在空中画圆你转动手机屏幕画面旋转 90°你开车转弯从面朝北变成面朝东。数学上在 2D绕原点旋转 θ点 P(x, y) 变成 P’(x’, y’)x x cosθ - y sinθ y x sinθ y cosθ这可以写成矩阵乘法后面讲矩阵会说但你现在只要知道“旋转就是变换公式”。在 3D绕 x/y/z 轴旋转有对应的 3×3 矩阵或者用四元数。Unity 里你写transform.Rotate(0,90,0);就是在把物体绕 y 轴旋转 90 度。2.3 缩放放大 / 缩小缩放 改变大小不改变方向如果缩放比例为正。点 P(x, y, z)缩放比例 S(sx, sy, sz)缩放后 P’(sx * x, sy * y, sz * z)。如果 sxsysz这叫“等比缩放”物体不会变形只是整体变大/变小。Unity 里transform.localScalenewVector3(2,2,2);// 放大 2 倍这会让物体在三个轴上都放大两倍。三、从点的视角看坐标怎么一步步被“变换”想象有一个点 P它经历了这几件事在原点附近画出来整体往右挪了 3 米平移绕原点旋转了 90 度旋转再整体放大 2 倍缩放。每动一次它的坐标就会变一次原始P0(x, y)平移后P1 P0 T旋转后P2 R * P1缩放后P3 S * P2。坐标变换 对坐标做一系列算术操作加、乘矩阵、乘比例。四、再具体一点用矩阵把平移旋转缩放统一管理略带点线性代数不用矩阵也能理解坐标变换但在游戏/图形这行你迟早要面对矩阵。我用最少的数学把这件事说清楚。4.1 为什么要矩阵——因为变换多了手动算会疯你可以这样想平移P’ P T旋转P’ R * P缩放P’ S * P问题来了如果你对一个点先缩放再旋转再平移怎么写如果场景里有 10 个祖孙层级物体每层都有自己的平移、旋转、缩放你要怎么把最里层点的最终世界坐标算出来手动一层层代入会很噩梦。矩阵的作用就是把“平移旋转缩放”这些操作统一写成一个 4×4 矩阵 M点用“齐次坐标”写成 4×1 列向量这样所有变换都可以写成P’ M * P。多次变换叠加就是多个矩阵相乘M_total M3 * M2 * M1。Unity 中transform.localToWorldMatrix就是一个典型的 4×4 变换矩阵。4.2 不用死记矩阵形式只要知道矩阵“打包变换”你现在不需要把每个矩阵的元素背下来只要记住一句关键话在图形/游戏世界里一个“4×4 变换矩阵”通常就是“先缩放、再旋转、再平移”的打包结果。因此只要你有了一个 transform里边有 position/rotation/scale引擎就能帮你生成一个矩阵 M把任何子点的“局部坐标”乘上这个矩阵 M就能得到“世界坐标”。通俗点说矩阵 一个物体“从自己空间到世界空间”的翻译官。五、游戏案例 1角色移动——本地坐标 vs 世界坐标5.1 问题按 W 键角色到底往哪走在第三人称 / FPS 游戏里你按 W 键角色“向前走”如果角色没转身“前”是世界的某个方向如果角色已经转向了“前”是角色面朝的方向而不是世界的 Z 轴。这里就涉及一个核心概念“前”是哪个方向要以谁为参考5.2 以世界为参考简单粗暴的移动最简单的写法// 世界坐标系下向 z 轴正方向移动transform.positionnewVector3(0,0,1)*speed*Time.deltaTime;这表示不管你角色面朝哪只要按 W就朝世界 z 正方向走。适合“固定摄像机”或者“顶视 RTS”类游戏但不适合“角色跟随摄像机转身”的 3D 动作游戏。5.3 以角色自己为参考本地坐标移动大多数 3D 动作/FPS需要的是角色按 W一直朝自己的“前方”移动。在 Unity 里transform.forward表示角色在世界坐标系中的“前方方向”一个单位向量。所以移动写成transform.positiontransform.forward*speed*Time.deltaTime;这里transform.forward是一个典型的“坐标变换”结果在角色自己的局部坐标里“前”是 (0, 0, 1)通过角色的旋转矩阵把 (0, 0, 1) 转换到世界坐标系中就得到了一个新的向量transform.forward再用它来移动就相当于在世界空间里沿着“角色的前方方向”移动。你可以这样理解“局部方向”“旋转变换” → “世界方向”这是最核心的方向坐标变换。六、游戏案例 2武器绑定手上——父子坐标变换6.1 需求手动一摆武器跟着走在角色身上挂武器常见做法在角色的骨骼上有一个“Hand_R”骨骼节点武器作为 Hand_R 的子物体设置武器的localPosition和localRotation来调整握持姿势之后角色播放动画时骨骼变换会带动武器一起动。6.2 数学视角局部坐标 父矩阵 世界坐标设武器在手坐标系中的局部坐标位置和旋转 Pw_local手骨骼的世界变换矩阵 M_hand武器自身的局部变换矩阵 M_weapon_local武器的世界矩阵 M_weapon_world则M_weapon_world M_hand * M_weapon_local再换成点的视角P_weapon_world M_hand * P_weapon_local理解成日常话就是“武器在手心这里相对偏一点点局部再加上手整体在世界的位置和旋转就能算出武器到底在世界什么位置、朝向哪里。”Unity 里你几乎不用管这些矩阵细节只要weapon.transform.parenthandTransform;weapon.transform.localPositionoffsetPosition;weapon.transform.localRotationoffsetRotation;之后所有坐标变换会自动完成。七、游戏案例 3摄像机跟随与绕点旋转7.1 摄像机跟着角色走平移 旋转的组合典型的第三人称视角摄像机永远在角色后上方一段距离角色前进摄像机跟着平移鼠标左右移动摄像机绕角色旋转角色也可跟着转身。设定角色位置P角色朝向方向forward摄像机相对角色的“局部偏移”比如在角色背后 5 米上方 3 米。可以在角色坐标系中写成 offset_local (0, 3, -5)。真正的相机位置要在世界坐标系里算// 把局部偏移变换到世界空间Vector3offset_worldcharacterTransform.TransformDirection(offset_local);// 或更严格TransformPoint把原点也平移进来camera.positioncharacterTransform.positionoffset_world;这里用到的 Unity 函数TransformDirection(vec)把一个“局部方向向量”变换到世界方向只考虑旋转和缩放不加平移TransformPoint(point)把局部坐标点变换到世界坐标包括平移。你可以理解为offset_local 是“在角色自己的轴里摄像机该在哪”TransformDirection/TransformPoint 做了一次“从角色空间到世界空间”的坐标变换得到真正的世界坐标位置。7.2 绕角色旋转相机以角色为中心旋转坐标系鼠标左右移动时你希望相机绕角色转而不是角色绕相机转。简化版逻辑记录一个“相机相对角色的球坐标”极坐标距离 r水平角 yaw俯仰角 pitch鼠标左右动修改 yaw鼠标上下动修改 pitch再把 (r, yaw, pitch) 转回 3D 直角坐标就是一个坐标变换得到 offset_local再像刚才那样把 offset_local 转成世界坐标。这个过程本质就是我们用了一种更适合描述“绕着一个点转圈”的坐标系极坐标/球坐标再把它转换回直角坐标系用来画图、渲染。八、游戏案例 4缩放——角色变大变小、UI 自适应、攻击判定缩放看起来简单但实战用途挺多。8.1 Boss 变大整体缩放模型有些游戏里Boss 激怒后会突然变大boss.transform.localScalenewVector3(2,2,2);// 放大 2 倍效果模型坐标系里的所有点都乘以 2所有子物体、武器、挂在身上的特效也跟着放大。有几点需要注意碰撞体Collider是否同步缩放Unity 大部分 Collider 会受 localScale 影响Box、Sphere 等但有时需要手动调整参数以保证准确。攻击范围 / 判定圆 / 触发器是否同步放大常常在代码里根据 scale 调整半径floatscaledRadiusbaseRadius*transform.lossyScale.x;// 假设等比缩放8.2 UI 缩放屏幕分辨率变了UI 如何适配UI 系统里坐标一般在“屏幕空间”坐标系下工作屏幕宽度从 1920 变 2560UI 元素的 anchor / pivot 决定它如何缩放、对齐RectTransform 的坐标变换里也隐含着平移缩放。比如一个血条在屏幕左上角可用相对屏幕宽高的比例来确定它的位置当分辨率变化时通过 Canvas Scaler RectTransform 自动做缩放和平移的坐标变换让它保持在视觉上的“同一位置”。本质还是“屏幕像素坐标系”和“UI 布局坐标系”之间的变换。九、父子层级里的“坐标变换链”骨骼动画的本质再稍微往进阶一点这个思想在骨骼动画里体现得淋漓尽致。9.1 每块骨骼都有自己的局部变换一个角色骨骼层级大致是RootSpineShoulderArmForearmHandWeapon每个骨骼都有localPosition相对父骨骼localRotationlocalScale。当你播放一段跑步动画时动画系统在每一帧更新每块骨骼的局部变换然后从 Root 开始一层层做“局部→父→世界”的矩阵乘法得到每块骨骼在世界坐标系下的最终变换再驱动蒙皮网格SkinMesh里的每个顶点做相应的坐标变换。这是一条典型的“坐标变换链”P_world M_root * M_spine * M_shoulder * M_arm * M_forearm * M_hand * P_local你不需要在代码里手写这堆运算引擎会帮你做完但理解这件事有助于你调试骨骼问题做一些 IK反向动力学效果比如脚贴地实现攻击判定通过骨骼位置计算武器路径。十、再往“数学一点”组合变换顺序很重要平移 旋转 缩放的组合有一个非常关键的坑变换顺序不一样结果会不一样。简单举个 2D 例子先平移再旋转 VS 先旋转再平移。10.1 先平移再旋转绕世界原点转圈假设点 P0(1,0)操作平移 T(1,0) → P1 (2,0)再绕原点旋转 90° → P2 (0,2)。画出来你会发现这个点是在“先从右边往外挪一点再绕原点转”的。视觉效果绕世界原点旋转。10.2 先旋转再平移绕自身局部原点平移同样起点 P0(1,0)操作先绕原点旋转 90° → P1(0,1)再平移 T(1,0) → P2(1,1)。视觉效果先把形状转好再整体平移。这两个结果不同。在矩阵里表现为M_total T * R ≠ R * T。在游戏中这也极其常见有时候你想“绕物体自身中心旋转再移动”有时候你想“先移动到某个位置再绕世界原点旋转”。理解顺序的重要性能帮你避免很多“相机绕圈绕错中心”“物体旋转古怪”的 BUG。十一、把整篇压成一张“坐标变换小抄”最后用一张“脑内小抄”的形式把关键点帮你捋一下。以后做游戏/看代码/学数学都能快速想起来。11.1 概念层面坐标系 给点编号码的规则世界坐标系整个场景的统一参考系局部坐标系某个物体/骨骼自己的参考系。坐标变换 在不同坐标系之间翻译局部 → 世界世界 → 摄像机屏幕 → UI等等。三大基本操作平移加一个向量位置变化旋转乘一个旋转矩阵/四元数方向变化缩放乘一个缩放矩阵大小变化。11.2 数学/实现层面平移P P T旋转2D 例子x x cosθ - y sinθ y x sinθ y cosθ缩放P (sx * x, sy * y, sz * z)组合变换用 4×4 矩阵一次性打包多层变换通过矩阵相乘叠加顺序很重要M_total M3 * M2 * M1。11.3 游戏应用层角色移动世界方向移动直接加(0,0,1)角色“前方向”移动加transform.forward。武器绑定手上武器的 localPosition/localRotation 相对于手骨骼手骨骼变换再通过矩阵链传到世界。摄像机跟随 / 绕角色旋转使用“局部偏移 坐标变换”得出世界位置。缩放Boss 变大、技能范围变大UI 自适应屏幕碰撞范围依据 scale 调整。骨骼动画、IK一连串父子变换链每帧把局部变换算到世界空间。十二、一句真正能记住的话收尾把这篇东西浓缩到一句最大白话里所谓“坐标变换平移 旋转 缩放”就是告诉你同一个点/物体在不同“参考系”下坐标不一样我们用平移、旋转、缩放的组合把这些坐标在各种坐标系之间来回“翻译”。数学上这是解析几何 矩阵运算游戏里它就是角色能走能转武器能跟着手一起挥摄像机能跟着你转圈UI 能适配不同分辨率骨骼动画能让模型活起来。当你下次写出transform.positiontransform.forward*speed*Time.deltaTime;weapon.parenthand;camera.positioncharacter.positioncharacter.TransformDirection(offset);可以在心里补一句“哦这几行就是在做坐标变换——平移 旋转 缩放的组合让虚拟世界动起来。”