【Unity】关于transform.TransformPoint的坐标转换

本文详细介绍了在Unity中如何利用TransformPoint和InverseTransformPoint方法解决复杂UI结构下的位移动画问题,实现子物体间的精确移动与重叠。

文章转自马尧shawn

之前在做项目的时候,有一个需求。需要对UI的操作对象进行一个位移动画,移动到另一参照物上。由于UI结构比较复杂,操作对象与参照对象,分别是不同父物体下的子物体,这就涉及到了本地坐标和世界坐标的转换。查了下API,发现Unity已经提供好了相应的接口,就是Transform.TransformPoint。于是只要理清相对坐标的概念,就非常的好处理了。


如图,创建了4个GameObject(Cube),我现在的目的是,再不改变obj4的父物体对象的情况下,让obj4与obj1重叠。由于obj4是obj3的子物体,那么obj4在Inspector面板下展示的坐标是相对obj3的本地坐标。如果想让obj4与obj1重叠,只局限于本地坐标的计算,是不可能得出想要的结果的。

我们必须通过转换成世界坐标系,再转换回本地坐标系得出想要的结果。

由于obj1使我们的目标,它相对于我们想要移动的对象的世界坐标为:

V1 =目标对象.transform.TransformPoint(操作对象.transform.localPosition);


世界坐标已经找到,再将此相对的世界坐标转换成操作对象的本地坐标:

操作对象.transform.InverseTransformPoint(v1);


所得的结果就是现在obj4与obj1重叠所需的本地坐标了。

为了方便测试,简单的写了点编辑器,证明结论正确。



最终测试代码如下:


 
  1. using UnityEngine;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. public class InversePosition : MonoBehaviour
  5. {
  6. public List<Transform> posList;
  7. [ HideInInspector]
  8. public Transform selectTransform;
  9. [ HideInInspector]
  10. public Transform targetTransform;
  11. void Start()
  12. {
  13. Print();
  14. }
  15. public void Print()
  16. {
  17. //操作的obj的世界坐标
  18. Debug.Log( string.Format( "选择的物体({0})的世界坐标:{1}", selectTransform.name, selectTransform.transform.position));
  19. //操作的obj的本地坐标
  20. Debug.Log( string.Format( "选择的物体({0})的本地坐标:{1}", selectTransform.name, selectTransform.transform.localPosition));
  21. //目标obj的世界坐标
  22. Debug.Log( string.Format( "目标物体({0})的世界坐标:{1}", targetTransform.name, targetTransform.transform.position));
  23. //目标obj的本地坐标
  24. Debug.Log( string.Format( "目标物体({0})的本地坐标:{1}", targetTransform.name, targetTransform.transform.localPosition));
  25. //目标obj相对于操作obj的世界坐标(trabsform.TransformPoint)
  26. Vector3 v4 = targetTransform.transform.TransformPoint(selectTransform.localPosition);
  27. Debug.Log( string.Format( "目标obj相对于选择obj的世界坐标(TransformPoint):{0}", v4));
  28. //操作目标的最终位置
  29. Debug.Log(selectTransform.transform.InverseTransformPoint(v4));
  30. }
  31. }

综上,在能确定目标位置的情况下,将某一子物体移动到该位置。都可以通过tranform.TransformPoint与transform.InverseTransformPoint两步转换获得。
<think> 首先,用户的问题是关于Unity中的transform.localToWorldMatrix的信息,包括使用方法、原理和应用场景。用户提供了多个引用来源,我需要从中提取相关信息。 回顾用户提供的引用: - 引用[1]:解释了localToWorldMatrix是本地坐标转世界坐标的矩阵信息,并与其他相关方法如TransformPoint等做了对比。 - 引用[2]:提到了Unity API中Transform类的属性,包括localToWorldMatrix,但没给出细节。 - 引用[3]:详细讨论了localToWorldMatrix的计算和验证,解释了旋转顺规、欧拉角和矩阵计算公式。关键点包括Unity的旋转顺规(世界系下是zxy顺序),以及如何从欧拉角计算矩阵。 - 引用[4]:简要提及了InverseTransformVector,但有关localToWorldMatrix的信息不多。 用户的核心问题是:"请问Unitytransform.localToWorldMatrix的使用方法和原理"。所以,我需要专注于回答这个部分。 从引用中提取关键点: - **使用方法**:localToWorldMatrix是一个矩阵,用于将点或向量从本地坐标系转换到世界坐标系。在Unity脚本中,可以直接访问transform.localToWorldMatrix来获取这个矩阵。 - **原理**:根据引用[3],localToWorldMatrix是基于物体的旋转、缩放和平移计算得到的。它涉及旋转顺规(zxy顺序)、欧拉角处理,以及矩阵乘法。具体来说: - 局部系到世界系的转换包括缩放、旋转和平移。 - 矩阵计算考虑了面板上的旋转角度值直接代入。 - localToWorldMatrix是4x4变换矩阵。 - **应用场景**:用于需要精确坐标转换的计算,如自定义渲染、物理模拟或UI元素放置。例如,当需要在世界空间中处理物体位置时,使用这个矩阵。 现在,构建我的回答结构: 1. **介绍**:简述localToWorldMatrix是什么。 2. **使用方法**:解释如何在Unity脚本中使用它。 3. **原理**:详细解释矩阵的计算原理,基于引用[3]的信息。 4. **应用场景**:给出一些常见用途。 5. **相关问题**:根据指令,生成相关问题。 回答必须遵循系统级指令: - 所有行内数学表达式使用$...$格式。 - 独立公式使用$$...$$格式单独成段。 - 使用中文回答。 - 引用末尾添加引用标识,如[^1]。 在回答中引用信息时,引用来源: - 引用[1]:概述信息。 - 引用[3]:详细原理和计算。 - 其他引用次要。 最终回答应包括: - 清晰的结构。 - 相关数学表达式。 - 末尾生成相关问题。 生成相关问题示例: 1. localToWorldMatrix在性能优化中的应用? 2. 如何手动计算localToWorldMatrix? 3. localToWorldMatrix与TransformPoint的区别? </think> ### Unitytransform.localToWorldMatrix的使用方法和原理 在Unity引擎中,`transform.localToWorldMatrix`是一个核心属性,用于将坐标点或向量从物体的本地坐标系(局部坐标系)转换到世界坐标系。它广泛应用于渲染、物理模拟和自定义脚本中。下面我将基于您提供的引用资料,逐步解释其使用方法、原理和应用场景。回答中涉及的关键点均来自官方文档和社区验证[^1][^3]。 #### 1. **使用方法** `transform.localToWorldMatrix`可直接在Unity的C#脚本中访问,返回一个4×4矩阵(`Matrix4x4`类型),该矩阵编码了物体的旋转、缩放和平移信息。使用步骤如下: - **基本调用**:在脚本中通过`transform.localToWorldMatrix`获取矩阵,然后应用于坐标转换。 ```csharp using UnityEngine; public class CoordinateExample : MonoBehaviour { void Update() { // 获取本地到世界坐标的矩阵 Matrix4x4 localToWorldMatrix = transform.localToWorldMatrix; // 定义一个本地坐标点(例如物体的局部原点) Vector3 localPoint = new Vector3(0, 0, 0); // 将本地坐标转换为世界坐标:使用矩阵乘法 Vector3 worldPoint = localToWorldMatrix.MultiplyPoint3x4(localPoint); Debug.Log("世界坐标位置:" + worldPoint); } } ``` - **注意事项**: - 此矩阵受物体的缩放、旋转和平移影响(例如,缩放会改变矩阵的缩放分量)。 - 与相关方法的区别: - `transform.TransformPoint`:直接转换位置,受缩放影响,但简化了矩阵操作[^1]。 - `transform.TransformVector`:转换方向或矢量,不受位置影响但受缩放影响[^1]。 - 优先使用`localToWorldMatrix`进行高效批量转换或自定义数学计算,避免频繁调用高级方法带来的开销。 #### 2. **原理** `transform.localToWorldMatrix`的原理基于仿射变换矩阵,包括旋转、缩放和平移。其计算涉及欧拉角和旋转顺规,Unity采用特定的坐标系规则[^3]。 - **数学基础**: - 变换矩阵是一个4×4矩阵,通用形式为: $$ \mathbf{M} = \begin{bmatrix} \mathbf{R} & \mathbf{t} \\ \mathbf{0} & 1 \end{bmatrix} $$ 其中,$\mathbf{R}$是3×3旋转-缩放矩阵,$\mathbf{t}$是3×1平移向量。 - 对于`localToWorldMatrix`,它表示从本地系(L)到世界系(W)的变换: $$ \mathbf{M}_{\text{localToWorld}} = \mathbf{T} \cdot \mathbf{R} \cdot \mathbf{S} $$ 这里,$\mathbf{S}$是缩放矩阵,$\mathbf{R}$是旋转矩阵,$\mathbf{T}$是平移矩阵。 - **旋转顺规和欧拉角处理**: - Unity的世界系旋转顺规为Z-X-Y顺序:物体先绕Z轴旋转,再绕X轴,最后绕Y轴(从其他坐标系到世界系的转换)[^3]。 - 例如,一个物体Inspector面板上的Rotation值(如Z=90°, X=30°, Y=0°)直接用于计算旋转矩阵$\mathbf{R}$。 - 旋转矩阵计算公式(基于Z-X-Y顺序): $$ \mathbf{R} = \mathbf{R}_y(\theta_y) \cdot \mathbf{R}_x(\theta_x) \cdot \mathbf{R}_z(\theta_z) $$ 其中,$\theta_z,\theta_x,\theta_y$是面板上的欧拉角值(单位:弧度)。 - **面板角度规则**:Inspector中的旋转角度值直接用于局部到世界转换(正值代入),而世界到局部转换需取其负值[^3]。 - 示例:如果面板角度为$(\theta_z, \theta_x, \theta_y)$,则`localToWorldMatrix`使用这些值;其逆矩阵`worldToLocalMatrix`使用$(-\theta_y, -\theta_x, -\theta_z)$。 - 缩放和平移:缩放矩阵$\mathbf{S}$基于物体的`lossyScale`(全局缩放),平移矩阵$\mathbf{T}$基于物体的世界位置`position`。 - **矩阵验证和计算**: - 引用[3]通过实验验证了矩阵的计算过程。例如,给定一个物体的欧拉角(Z=90°, X=30°, Y=0°),其`localToWorldMatrix`可通过以下步骤手动计算: 1. 计算各轴旋转矩阵(使用标准旋转矩阵公式)。 2. 按Z-X-Y顺序相乘:$\mathbf{R} = \mathbf{R}_y(0) \cdot \mathbf{R}_x(30^\circ) \cdot \mathbf{R}_z(90^\circ)$。 3. 结合缩放和平移生成完整矩阵。 - 逆矩阵关系:`worldToLocalMatrix`是`localToWorldMatrix`的逆矩阵,可通过`Matrix4x4.Inverse()`计算[^3]。 #### 3. **应用场景** - **渲染和着色器**:在自定义Shader中,使用此矩阵将顶点从模型空间(本地)转换到世界空间,实现光照或投影计算。 - **物理和碰撞检测**:精确计算物体间的世界位置关系,例如在射线检测(Raycast)中转换坐标。 - **UI和动画**:动态放置UI元素或处理骨骼动画时,确保坐标一致性。 - **性能优化**:对多个点进行批量转换时,直接使用矩阵比逐点调用`TransformPoint`更高效[^1]。 #### 相关问题 1. localToWorldMatrix在自定义着色器中如何应用? 2. 如何手动计算localToWorldMatrix的旋转分量? 3. localToWorldMatrix与transform.worldToLocalMatrix的性能差异是什么?
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值