Transform 相对位置变换,坐标系转换

本文详细介绍了在Unity中如何通过坐标系转换确保一个对象相对于另一个对象保持不变。通过使用Transform.InverseTransformDirection和Transform.TransformPoint进行位置转换,以及Quaternion运算和TransformDirection来处理角度。在处理对象的相对位置和角度时,考虑了Scale不为1的情况,并提出了使用矩阵变换矩阵以忽略缩放影响的解决方案。此外,还指出了仅通过一个轴转换的第二种方法在某些情况下可能存在问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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 来实现上面的过程。                                

                 

  

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值