Unity复杂的旋转-欧拉角和四元数

学了那么久 其实对Unity的欧拉角和四元数并没有很深刻的认识…所以就此开篇稍微介绍一下

  • 我们首先知道的是,在Unity中有两种方式表示旋转。一种是欧拉角,还有一种就是四元数,那其中的区别有哪些呢?我们先分别介绍一下。

一.欧拉角

欧拉角最容易表示,用三个变量X,Y,Z可以直观的表示绕着某个轴的旋转角度。

在Unity里就是Transform组件的Rotation里的X Y Z三个变量代表了欧拉角
Unity复杂的旋转-欧拉角和四元数_第1张图片

二.四元数

四元数相比于欧拉角就比较复杂了,由四个变量组成(在Unity中称为X,Y,Z,W),但是这些变量的值不代表旋转角度,所以可能给你一个向量(0。7,0,0,0.7)你并不知道实际旋转的角度,当然四元数的详细解释需要数学方面的深入研究,有兴趣的可以自行查找有关资料

  • 因为在Unity没有可视化界面可以调整四元数(因为真的调了也不直观看到旋转的角度),所以我们只能用脚本来访问

三.脚本中内容

欧拉角如果在脚本中表示呢?
是不是想到之前图中的那个Rotation,那你是不是自然而然的想到了通过transform.rotation访问呢?如果你是这样想的,那就错了!
在Unity中transform.rotation代表的是四元数!附上官网证明!
Unity复杂的旋转-欧拉角和四元数_第2张图片
那到底如何表示欧拉角呢?其实表示很简单,并附上官网解释

transform.eulerAngles =new Vector3(20,300,40);

Unity复杂的旋转-欧拉角和四元数_第3张图片
当我们以上述代码运行后会发现Rotation中的Y值是-60,那是因为面板上的Rotation中的X Y Z值范围是在(-180,180),对于代码中超出的部分会自动进行计算映射到范围内
Unity复杂的旋转-欧拉角和四元数_第4张图片

四元数的代码表示就是之前的transform.rotation,那你肯定会想欧拉角和四元数之前能否转换呢,知道其中一个的值,如果改变成对方呢?代码如下

//欧拉角->四元数 
//通过Quaternion.Euler() 传递一个Vector3向量的欧拉角
transform.rotation = Quaternion.Euler(new Vector3(20, 300, 40));

//四元数->欧拉角
transform.rotation.eulerAngles;//对你没看错 直接可以转换获取

三.区别

欧拉角:
  • 优点:三个角度组成,直观,容易理解
  • 优点:可以进行从一个方向到另一个方向旋转大于180度的角度
  • 缺点:死锁问题——万向节死锁 万向节死锁介绍
四元数
  • 优点:不存在万向节死锁问题
  • 优点:存储空间小,计算效率高
  • 缺点:单个四元数不能表示在任何方向上超过180度的旋转。
  • 缺点:数字表示不直观

四.常用API

  • Quaternion.LookRotation() 使其转向某个方向
    Unity复杂的旋转-欧拉角和四元数_第5张图片
    函数传递的参数的一个Vector3的向量 这个向量表示的是要看向的向量,通常用目标的positon和自身的position进行相减求得此向量
Vector3 pos = target.transform.position - transform.position;
transform.rotation = Quaternion.LookRotation(pos);

是不是觉得和transform.LookAt()效果很像…

//和上面代码得到的效果相同
transform.LookAt(target.transform);
  • Quaternion.Slerp() 平滑进行转动动画
    Unity复杂的旋转-欧拉角和四元数_第6张图片
    函数传递的参数分别是 当前GameObject的四元数、目标要转向的四元数 和 一个插值时间
    我们看个例子
void LookAtTarget()
    {
        if (Input.GetKey(KeyCode.Space))
        {
            Vector3 dir = target.transform.position - transform.position;
            dir.y = 0;//不让Player有y轴上的倾角
            Quaternion target = Quaternion.LookRotation(dir);
            transform.rotation = Quaternion.Slerp(transform.rotation, target, Time.deltaTime);
        }
    }

我们将上述的LookAtTarget()方法放到Update()函数中进行执行
就可以看到平滑的转动

Unity复杂的旋转-欧拉角和四元数_第7张图片

  • Quaternion.Lerp() 说实话个人用起来和Slerp()区别不大
    Unity复杂的旋转-欧拉角和四元数_第8张图片
    图中红线框出来的就是区别:使用Lerp()进行旋转的速度较快,但是在旋转角度较大的时候,效果会糟一点。

  • Quaternion.RotateTowards()
    Unity复杂的旋转-欧拉角和四元数_第9张图片
    传递两个四元数,和一个角度增量值,使第一个四元数逐渐趋近于第二个四元数并最终相等

void Update()
    {
        float step = 3 * Time.deltaTime;
        transform.rotation = Quaternion.RotateTowards(transform.rotation,target.transform.rotation,step);
    }

结果就是当前物体的四元数和目标的四元数相等

  • Transform.RotateAround()
    Unity复杂的旋转-欧拉角和四元数_第10张图片
    传递一个参照点point、绕哪个轴转axis和增量角度angle
void Update()
    {
        float step = 3 * Time.deltaTime;
        transform.RotateAround(target.transform.position,Vector3.up,step);
    }

Unity复杂的旋转-欧拉角和四元数_第11张图片

五.总结

差不多基础概念就这些了吧,如果要深入了解的话,建议还是看API,并且自己多动手尝试一下数据~

你可能感兴趣的:(U3d学习小知识)