Transform.LookAt解析

    xiaoxiao2022-07-05  165

    LookAt函数的定义如下

    void LookAt(Transformtarget,Vector3worldUp = Vector3.up);

    target    :Object to point towards worldUp:Vector specifying the upward direction.

    根据官方的文档描述,该函数的功能是,旋转自身,使得当前对象的正z轴指向目标对象target所在的位置。

    而对于worldUp的描述是,在完成上面的旋转之后,继续旋转自身,使得当前对象的正y轴朝向与worldUp所指向的朝向一致。这里所说的朝向一致并不是指两个向量方向完全一致,这就是让人迷惑的地方。

    现使用一个例子进行解析

    使摄像头指向一个物体,摄像头的位置是(0,30,60),目标物体的位置是(0,0,0),代码如下

    using UnityEngine; using System.Collections;

    public class lookAtTest : MonoBehaviour {

    // Use this for initialization public Transform target; void Start () { target.position = Vector3.zero; transform.position = new Vector3(0, 30, 60); Vector3 diff = target.position - transform.position; transform.LookAt(target); }

    }

    现在为了解析LookAt函数的计算过程,使用如下代码:

    using UnityEngine; using System.Collections;

    public class lookAtTest : MonoBehaviour {

    public Transform target; void Start () { target.transform.position = Vector3.zero; transform.position = new Vector3(0, 30, 60); Vector3 diff = target.position - transform.position; Quaternion q = Quaternion.FromToRotation(Vector3.forward, diff); Vector3 newUp = q * Vector3.up; Quaternion qNew = Quaternion.FromToRotation(newUp,Vector3.up); transform.rotation = qNew * q; }

    }

    该计算过程中,q的计算是正确的,qNew的计算是将新旋转后的y轴旋转到Vector3.up,经过这样运算后和前面LookAt的运行结果比对可以发现该计算是错误的。错误发生在qNew的计算上。

    经过多次测试后发现,worldUp的描述“在完成上面的旋转之后,继续旋转自身,使得当前对象的正y轴朝向与worldUp所指向的朝向一致”里的朝向一致,指的是新旋转后的y轴与worldUp在该对象初次旋转后的xy平面上的投影向量一致。也就是说,worldUp应取它在应用了旋转量q后的xy平面的投影量。

    新代码如下

    using UnityEngine; using System.Collections;

    public class lookAtTest : MonoBehaviour {

    public Transform target; void Start() { target.transform.position = Vector3.zero; transform.position = new Vector3(0, 30, 60); Vector3 diff = target.position - transform.position; Quaternion q = Quaternion.FromToRotation(Vector3.forward, diff); Vector3 n = q * Vector3.forward; Vector3 worldUp = Vector3.up; float dirDot = Vector3.Dot(n, worldUp); Vector3 vProj = worldUp - n * dirDot; //worldUp在xy平面上的投影量 vProj.Normalize(); float dotproj = Vector3.Dot(vProj, newUp); float theta = Mathf.Acos(dotproj) * Mathf.Rad2Deg; Quaternion qNew = Quaternion.AngleAxis(theta, n); Quaternion qall = qNew * q; transform.rotation = qall; }

    }


    作者:Justin__Ko 来源: 原文:https://blog.csdn.net/kfqcome/article/details/19202833 版权声明:本文为博主原创文章,转载请附上博文链接!

    最新回复(0)