Unity基础:Transform组件详解——位置、旋转与缩放的坐标系

📅 2026/7/16 12:44:24
Unity基础:Transform组件详解——位置、旋转与缩放的坐标系
Unity基础Transform组件详解——位置、旋转与缩放的坐标系大家好欢迎回到Unity教程系列。前面九篇文章我们学习了Unity编辑器的各个核心面板从今天开始我们要进入具体组件的学习了。而Transform组件毫无疑问是最重要的起点。为什么说Transform最重要因为它是Unity中唯一一个每个GameObject都必然拥有且不可移除的组件。没有Transform一个GameObject甚至无法存在于场景中。Position位置、Rotation旋转、Scale缩放这三个属性构成了3D空间中物体存在的全部信息。这篇文章的内容虽然偏基础但对于后续学习物理、动画、寻路等高级系统都有直接的影响。请务必把每个概念都理解透彻。一、Unity的坐标系系统1.1 左手坐标系在深入Transform之前我们必须先理解Unity使用的坐标系类型。Unity采用左手坐标系Left-Handed Coordinate System。 什么是左手坐标系伸出你的左手让食指指向右X轴正方向中指指向前Z轴正方向那么拇指自然指向上Y轴正方向。这就是Unity的世界坐标系方向。与左手坐标系相对的是右手坐标系很多3D软件如3ds Max、Maya使用右手坐标系两者的区别在于Z轴的正方向是相反的。对开发者的实际影响如果你从3D建模软件导入模型到Unity可能需要进行坐标轴转换。一般来说从Blender导入的模型Y轴和Z轴可能需要调整。1.2 世界坐标系World Coordinate System世界坐标系是场景中的绝对参考框架。它像一个巨大的、不可移动的网格覆盖整个场景空间X轴红色指向右方Y轴绿色指向上方Z轴蓝色指向前方世界坐标原点是 (0, 0, 0)。场景中每个物体的世界坐标World Position就是它相对于这个原点的位置。在Scene视图中你可以通过右上角的坐标轴指示器Scene Gizmo看到当前的世界坐标轴方向。点击Gizmo上的X、Y、Z轴可以快速切换到标准视角。1.3 局部坐标系Local Coordinate System局部坐标系是相对于物体自身的坐标框架。每个GameObject都有自己的局部坐标空间物体的前方forward是它自身Z轴的正方向在Inspector中显示为蓝色箭头物体的上方up是它自身Y轴的正方向绿色物体的右方right是它自身X轴的正方向红色当你使用Transform的Translate工具并切换到Local模式时Gizmo的轴向会与物体的自身朝向对齐而不是世界坐标轴。1.4 编辑器中的坐标模式切换在Unity编辑器顶部的Toolbar中有两个与坐标相关的切换按钮Global / Local切换Global模式Transform工具的Gizmo与世界坐标轴对齐。拖拽红色X轴箭头物体严格沿世界X方向移动。Local模式Gizmo与物体自身的坐标轴对齐。拖拽红色箭头物体沿它认为自己的X方向移动。 使用建议大多数场景搭建工作用Global模式更方便对齐世界网格。但当你需要沿一个旋转过的物体的前方移动时必须切换到Local模式。我习惯在二者之间频繁切换。Center / Pivot切换CenterGizmo显示在物体包围盒的几何中心位置PivotGizmo显示在物体的轴心点位置在建模软件中设定二、Position——位置2.1 Inspector中的Position在Inspector的Transform组件中Position由三个数值组成X水平位置、Y垂直位置、Z深度位置。⚠️ 这里有一个非常重要的概念Inspector中显示的Position值是局部坐标Local Position即相对于父物体的位置而非世界坐标。如果一个物体没有父物体在Hierarchy的根级它的Local Position就等于World Position。如果物体有父物体它的World Position 父物体的World Position 自身的Local Position。2.2 代码中操作位置// 获取和设置世界坐标Vector3worldPostransform.position;transform.positionnewVector3(0,5,0);// 获取和设置局部坐标Vector3localPostransform.localPosition;transform.localPositionnewVector3(1,2,3);// 只修改某个分量transform.positionnewVector3(10,transform.position.y,transform.position.z);// 使用Translate方法移动物体transform.Translate(Vector3.forward*speed*Time.deltaTime);// Translate的相对空间模式transform.Translate(Vector3.forward,Space.World);// 沿世界Z轴移动transform.Translate(Vector3.forward,Space.Self);// 沿自身Z轴移动默认2.3 Transform的方向属性Transform提供了几个便捷的方向属性来获取物体的朝向向量// 物体自身坐标轴在世界空间中的方向Vector3forwardtransform.forward;// 物体的前方自身Z轴在世界空间的方向Vector3uptransform.up;// 物体的上方自身Y轴Vector3righttransform.right;// 物体的右方自身X轴这些属性是只读的它们基于物体的旋转自动计算。你可以用它们来让物体沿其朝向方向移动// 让物体沿它面对的方向前进transform.positiontransform.forward*speed*Time.deltaTime;2.4 Vector3结构体详解 Vector3是Unity中使用频率最高的数据结构之一它表示一个三维向量或坐标点。// 创建Vector3的多种方式Vector3anewVector3(1f,2f,3f);Vector3bVector3.zero;// (0, 0, 0)Vector3cVector3.one;// (1, 1, 1)Vector3dVector3.up;// (0, 1, 0)Vector3eVector3.down;// (0, -1, 0)Vector3fVector3.forward;// (0, 0, 1)Vector3gVector3.back;// (0, 0, -1)Vector3hVector3.right;// (1, 0, 0)Vector3iVector3.left;// (-1, 0, 0)// Vector3的常用运算Vector3sumab;// 向量加法Vector3diffa-b;// 向量减法Vector3scaleda*2f;// 标量乘法floatdistanceVector3.Distance(a,b);// 两点之间的距离Vector3normalizeda.normalized;// 归一化长度变为1floatmagnitudea.magnitude;// 向量的长度Vector3lerpVector3.Lerp(a,b,0.5f);// 线性插值三、Rotation——旋转3.1 Inspector中的RotationInspector中的Rotation也由X、Y、Z三个值组成表示绕对应轴的旋转角度欧拉角Euler Angles单位是度°。 欧拉角是最直观的旋转表示方式——绕X轴旋转多少度、绕Y轴旋转多少度、绕Z轴旋转多少度。但欧拉角有一个著名的问题万向节死锁Gimbal Lock。这会导致在某些角度下丢失一个旋转自由度。这也是为什么Unity内部使用四元数Quaternion来存储旋转仅在Inspector中显示为欧拉角。3.2 代码中操作旋转// 使用欧拉角transform.rotationQuaternion.Euler(0,90,0);Vector3eulertransform.eulerAngles;// 局部旋转transform.localRotationQuaternion.identity;// 无旋转Vector3localEulertransform.localEulerAngles;// 使用Rotate方法旋转物体transform.Rotate(Vector3.up*speed*Time.deltaTime);transform.Rotate(Vector3.up*speed*Time.deltaTime,Space.World);// 让物体朝向某个目标transform.LookAt(targetTransform);transform.LookAt(targetTransform.position);3.3 Quaternion四元数四元数Quaternion是Unity内部使用的旋转表示方式。对于初学者来说你不需要深入理解四元数的数学原理那涉及到复数和高维数学只需要掌握以下使用方式// 创建四元数QuaternionidentityQuaternion.identity;// 无旋转等同于Euler 0,0,0Quaternionrot1Quaternion.Euler(0,90,0);// 从欧拉角创建Quaternionrot2Quaternion.LookRotation(Vector3.forward);// 面向指定方向// 旋转插值Quaternion.Lerp(from,to,t);// 线性插值速度不均匀Quaternion.Slerp(from,to,t);// 球面线性插值速度均匀推荐// 四元数乘法组合旋转Quaternioncombinedrot1*rot2;// 先应用rot1再应用rot2⚠️ 四元数乘法不满足交换律a * b不等于b * a。旋转的顺序很重要。3.4 旋转的常用模式// 让物体持续自转voidUpdate(){transform.Rotate(Vector3.up*30f*Time.deltaTime);}// 让物体平滑转向目标voidUpdate(){Vector3directiontarget.position-transform.position;QuaterniontargetRotationQuaternion.LookRotation(direction);transform.rotationQuaternion.Slerp(transform.rotation,targetRotation,5f*Time.deltaTime);}四、Scale——缩放4.1 Inspector中的ScaleScale控制物体在各个轴上的缩放比例。默认值为 (1, 1, 1)表示原始大小值大于1放大值等于1原始大小值小于1缩小负值镜像翻转4.2 代码中操作缩放// 获取和设置世界缩放Vector3worldScaletransform.lossyScale;// 只读考虑了父物体的缩放// transform.lossyScale 反映了物体在世界空间中的实际大小// 获取和设置局部缩放Vector3localScaletransform.localScale;// 可读写transform.localScalenewVector3(2,2,2);// 放大2倍// 等比例缩放transform.localScaleVector3.one*2f;4.3 lossyScale与localScale的区别 这是很多新手会混淆的概念localScale物体自身的缩放值Inspector中显示的Scale。这是一个可读写的属性。lossyScale物体在世界空间中的实际缩放——等于该物体及其所有父物体的localScale的乘积。这是一个只读属性。示例父物体localScale (2, 2, 2)子物体localScale (3, 3, 3)子物体的lossyScale (6, 6, 6)⚠️ 注意非均匀缩放各轴的缩放比例不同加上父物体的旋转可能会导致子物体的lossyScale计算变得复杂。在某些情况下Unity的Transform系统可能无法正确表示这种组合这时会出现剪切Shear变形。4.4 缩放对子物体的影响子物体的localScale与父物体的缩放是乘积关系。这意味着如果父物体缩放为(2,2,2)子物体localScale为(1,1,1)子物体实际显示为2倍大小子物体的localPosition也会受到父物体缩放的影响——子物体到父物体的实际距离 localPosition的距离 × 父物体的localScale五、Transform的父子关系5.1 父物体对子物体Transform的影响父子关系是Transform组件最核心的概念之一。子物体的Transform值是相对于父物体的子物体世界位置 父物体世界位置 父物体旋转 × (子物体局部位置 × 父物体缩放)简单理解移动父物体 → 所有子物体跟着移动旋转父物体 → 所有子物体跟着旋转围绕父物体的轴心缩放父物体 → 所有子物体跟着缩放5.2 代码中管理父子关系// 设置父物体childTransform.SetParent(parentTransform);childTransform.SetParent(parentTransform,false);// 保持世界坐标不变childTransform.SetParent(parentTransform,true);// 保持局部坐标不变// 解除父子关系childTransform.SetParent(null);// 获取父物体Transformparenttransform.parent;// 获取根物体层级最顶端的父物体Transformroottransform.root;// 遍历所有子物体foreach(Transformchildintransform){Debug.Log(child.name);}// 获取子物体数量intcounttransform.childCount;// 按索引获取子物体TransformfirstChildtransform.GetChild(0);// 按名称路径查找子孙物体Transformfoundtransform.Find(Child/Grandchild);5.3 SetParent的worldPositionStays参数// worldPositionStays true默认: 子物体的局部坐标会被重新计算使其世界坐标保持不变child.SetParent(newParent,true);// worldPositionStays false: 子物体的局部坐标不变世界坐标随父物体改变child.SetParent(newParent,false);六、Transform常用方法6.1 TransformDirection与InverseTransformDirection这些方法用于在世界方向与局部方向之间转换// 将局部方向转换为世界方向Vector3worldDirtransform.TransformDirection(Vector3.forward);// 将世界方向转换为局部方向Vector3localDirtransform.InverseTransformDirection(worldForward);6.2 TransformPoint与InverseTransformPoint这些方法用于在世界坐标与局部坐标之间转换点// 将相对于该Transform的局部坐标点转换为世界坐标点Vector3worldPointtransform.TransformPoint(newVector3(0,0,1));// 将世界坐标点转换为相对于该Transform的局部坐标点Vector3localPointtransform.InverseTransformPoint(worldPoint);6.3 DetachChildren将所有的子物体从当前物体下解放出来全部移到Hierarchy根级transform.DetachChildren();七、实战练习7.1 太阳系模拟用Transform父子关系创建一个简单的太阳系模型publicclassSolarSystem:MonoBehaviour{publicTransformsun;publicTransformearth;publicTransformmoon;voidUpdate(){// 太阳自转sun.Rotate(Vector3.up*10f*Time.deltaTime);// 地球绕太阳公转地球是太阳的子物体绕自身Y轴旋转则绕太阳转earth.Rotate(Vector3.up*50f*Time.deltaTime);// 月球绕地球公转moon.Rotate(Vector3.up*100f*Time.deltaTime);}}层级结构Sun ├── EarthLocalPosition设为(5,0,0) │ └── MoonLocalPosition设为(2,0,0)7.2 摄像机跟随用Transform实现一个简单的第三人称摄像机publicclassSimpleCameraFollow:MonoBehaviour{publicTransformtarget;// 跟随目标publicVector3offsetnewVector3(0,3,-5);// 偏移量publicfloatsmoothSpeed5f;voidLateUpdate(){Vector3desiredPositiontarget.positionoffset;Vector3smoothedPositionVector3.Lerp(transform.position,desiredPosition,smoothSpeed*Time.deltaTime);transform.positionsmoothedPosition;transform.LookAt(target);}}八、本篇总结✅ 本文核心知识点回顾Unity使用左手坐标系X轴红向右Y轴绿向上Z轴蓝向前Transform由Position位置、Rotation旋转、Scale缩放三部分组成Inspector中显示的是局部坐标相对于父物体代码中通过transform.position、transform.rotation、transform.localScale访问和修改Transform四元数Quaternion是Unity内部的旋转表示使用Slerp实现平滑旋转父子关系让子物体跟随父物体的Transform变化TransformPoint/InverseTransformPoint在世界坐标和局部坐标之间转换 下一篇文章将讲解GameObject与Component的核心架构思想彻底理解Unity的设计哲学。动手任务① 创建一个父物体和一个子物体分别调整它们的位置、旋转、缩放观察效果② 用代码控制一个物体绕另一个物体旋转公转③ 用LookAt实现一个物体始终面向另一个物体关于作者拥有多年Unity开发经验的游戏开发者专注Unity系统化教学与最佳实践分享。欢迎在评论区交流讨论