文章转自马尧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重叠所需的本地坐标了。
为了方便测试,简单的写了点编辑器,证明结论正确。
最终测试代码如下:
-
using UnityEngine;
-
using System.Collections;
-
using System.Collections.Generic;
-
public
class
InversePosition :
MonoBehaviour
-
{
-
public List<Transform> posList;
-
-
[
HideInInspector]
-
public Transform selectTransform;
-
[
HideInInspector]
-
public Transform targetTransform;
-
-
void Start()
-
{
-
Print();
-
}
-
-
public void Print()
-
{
-
//操作的obj的世界坐标
-
Debug.Log(
string.Format(
"选择的物体({0})的世界坐标:{1}", selectTransform.name, selectTransform.transform.position));
-
//操作的obj的本地坐标
-
Debug.Log(
string.Format(
"选择的物体({0})的本地坐标:{1}", selectTransform.name, selectTransform.transform.localPosition));
-
-
//目标obj的世界坐标
-
Debug.Log(
string.Format(
"目标物体({0})的世界坐标:{1}", targetTransform.name, targetTransform.transform.position));
-
//目标obj的本地坐标
-
Debug.Log(
string.Format(
"目标物体({0})的本地坐标:{1}", targetTransform.name, targetTransform.transform.localPosition));
-
-
//目标obj相对于操作obj的世界坐标(trabsform.TransformPoint)
-
Vector3 v4 = targetTransform.transform.TransformPoint(selectTransform.localPosition);
-
Debug.Log(
string.Format(
"目标obj相对于选择obj的世界坐标(TransformPoint):{0}", v4));
-
-
//操作目标的最终位置
-
Debug.Log(selectTransform.transform.InverseTransformPoint(v4));
-
}
-
}
综上,在能确定目标位置的情况下,将某一子物体移动到该位置。都可以通过tranform.TransformPoint与transform.InverseTransformPoint两步转换获得。