Transform.LookAt解析

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
来源:CSDN
原文:https://blog.csdn.net/kfqcome/article/details/19202833
版权声明:本文为博主原创文章,转载请附上博文链接!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值