1.在开发的时候有遇到需要做对某一个对象进行坐标系转换,比如需要一个对象a,需要时刻保持相对于A不变。 最简单的时 将a作为A的子物体。 这时候无论A怎么变换,a都相对A 是一致的。 这样做肯定是没问题的,而且简单。
2.但是呢! 也会碰到情况复杂,选择a 设置为A的子物体,可能会影响到其他的逻辑,所以不能做样做。那这时候就得通过计算来得到。 这里就要做坐标系转换。那么就需要用到Transform.TransformPoint 以及Transform.TransformDirection 。
3. 首先是做位移的计算。 对某个点进行坐标系转换,用 Transform.InverseTransformDirection 和 Transform.TransformPoint 就可以。
在初始化的时候 使用 Transform.InverseTransformDirection() 方法,将a的世界坐标,转化为相对于A的局部坐标。保存这个局部坐标,这个就是需要a一致保持的位置信息。
然后在A姿态发生变化时, 通过 Transform.TransformPoint 可以将刚保存的局部坐标,从A 坐标系转化到世界坐标系,这时候将得到的坐标赋值给a. 位置就可以实现相对A不变。
4. 然后就是要做角度也要相对A不变。 同样需要保存一个局部的角度信息
(1)第一种,直接保存相对的四元数信息。如下
Quaternion.Inverse(a.rotation) * A.rotation
在A发生变化后,在执行 Quaternion rot = defaultRot * A.rotation;
rot即是变化后a现对A角度一致的rotation.
(2)第二种 采用 transform.TransformDirection 。 这个是对向量进行坐标系转换,,所以就选一个轴在做。 用Forward 比较方便。
首先依旧是初始化的时候,记录相对方向。如下
DefauleDrec = A.InverseTransformDirection(a.forward);
在A发生变化后,在执行
Vector3 Rot01 = A.TransformDirection(DefauleDrec); // 将方向从A的坐标系转化到世界坐标系。
a.rotation = Quaternion.LookRotation(Rot01, transform.up); //然后在将旋转赋值到a
测试代码如下:
public Transform A;
public Transform a;
private Vector3 defaultPos=Vector3.zero;
private Vector3 DefauleDrec = Vector3.zero;
private Quaternion defaultRot;
// Start is called before the first frame update
void Start()
{
//记录子级初始的相对于父级的角度姿态。
DefauleDrec = A.InverseTransformDirection(a.forward);
defaultPos= A.InverseTransformPoint(a.position);
defaultRot = Quaternion.Inverse(a.rotation) * A.rotation;
}
// Update is called once per frame
void Update()
{
//方法一
//变换之后的位置计算
Vector3 Pos = A.TransformPoint(defaultPos);
//变换之后的放向计算
Quaternion rot = defaultRot * A.rotation;
a.position = Pos;
a.rotation = rot;
// 方法二
//变换之后的位置计算
Vector3 Pos01 = A.TransformPoint(defaultPos);
//变换之后的放向计算
Vector3 Rot01 = A.TransformDirection(DefauleDrec);
a.position = Pos01;
a.rotation = Quaternion.LookRotation(Rot01, transform.up);
}
补充: 此处代码会存在一些情况无法适用。
比如Scale 不为1. 假设碰到Scale不为一,就不能使用TransformDirection 这些内置矩阵。 需要重新创建变换矩阵。
过了N久之后回头来看,发现 ,不好意思,第二种方式是有问题的。 在坐标系转换过程中只通过一个向的切换不行的。起码要两个轴。所以如果真的是要通过直观的方向算,那么就先使用Quaternion.LookRotation()或者 Quaternion.FromToRotation将 Vector3的方向转换到四元数,再通过第一种方式切换坐标轴,最后在转为方向。
另外Scale 不为1 时,通过Matrix4x4.TRS(transform.position, transform.rotation, Vector3.one) (其中最后一项缩放要用单位向量,所以能够忽略缩放带来的影响)来得到变换矩阵。 然后通过Matrix4x4.inverse.MultiplyPoint以及Matrix4x4.MultiplyPoint 来实现上面的过程。