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


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

    在Unity里就是Transform组件的Rotation里的X Y Z三个变量代表了欧拉角


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

    因为在Unity没有可视化界面可以调整四元数(因为真的调了也不直观看到旋转的角度),所以我们只能用脚本来访问
    三.脚本中内容
    欧拉角如果在脚本中表示呢?
    是不是想到之前图中的那个Rotation,那你是不是自然而然的想到了通过transform.rotation访问呢?如果你是这样想的,那就错了!
    在Unity中transform.rotation代表的是四元数!附上官网证明!

    那到底如何表示欧拉角呢?其实表示很简单,并附上官网解释

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

    当我们以上述代码运行后会发现Rotation中的Y值是-60,那是因为面板上的Rotation中的X Y Z值范围是在(-180,180),对于代码中超出的部分会自动进行计算映射到范围内


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

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

    //四元数->欧拉角
    transform.rotation.eulerAngles;//对你没看错 直接可以转换获取
    1
    2
    3
    4
    5
    6
    三.区别
    欧拉角:
    优点:三个角度组成,直观,容易理解
    优点:可以进行从一个方向到另一个方向旋转大于180度的角度
    缺点:死锁问题——万向节死锁 万向节死锁介绍
    四元数
    优点:不存在万向节死锁问题
    优点:存储空间小,计算效率高
    缺点:单个四元数不能表示在任何方向上超过180度的旋转。
    缺点:数字表示不直观
    四.常用API
    Quaternion.LookRotation() 使其转向某个方向

    函数传递的参数的一个Vector3的向量 这个向量表示的是要看向的向量,通常用目标的positon和自身的position进行相减求得此向量
    Vector3 pos = target.transform.position - transform.position;
    transform.rotation = Quaternion.LookRotation(pos);
    1
    2
    是不是觉得和transform.LookAt()效果很像…

    //和上面代码得到的效果相同
    transform.LookAt(target.transform);
    1
    2
    Quaternion.Slerp() 平滑进行转动动画

    函数传递的参数分别是 当前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);
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    我们将上述的LookAtTarget()方法放到Update()函数中进行执行
    就可以看到平滑的转动

    Quaternion.Lerp() 说实话个人用起来和Slerp()区别不大

    图中红线框出来的就是区别:使用Lerp()进行旋转的速度较快,但是在旋转角度较大的时候,效果会糟一点。

    Quaternion.RotateTowards()

    传递两个四元数,和一个角度增量值,使第一个四元数逐渐趋近于第二个四元数并最终相等

    void Update()
    {
    float step = 3 * Time.deltaTime;
    transform.rotation = Quaternion.RotateTowards(transform.rotation,target.transform.rotation,step);
    }
    1
    2
    3
    4
    5
    结果就是当前物体的四元数和目标的四元数相等

    Transform.RotateAround()

    传递一个参照点point、绕哪个轴转axis和增量角度angle
    void Update()
    {
    float step = 3 * Time.deltaTime;
    transform.RotateAround(target.transform.position,Vector3.up,step);
    }
    1
    2
    3
    4
    5


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

  • 相关阅读:
    Treap仿set 模板
    线段树(区间更改,区间查最值)模板
    UVA 12345 Dynamic len(带修莫队)
    服务器配置环境以及部署项目流程
    使用SSH的scp命令行传输文件到远程服务器
    服务器部署javaweb项目
    在ubuntu服务器上安装mysql并配置外网访问
    在ubuntu服务器上配置tomcat
    在ubuntu服务器上配置jdk
    linux命令--解压与压缩
  • 原文地址:https://www.cnblogs.com/ly570/p/11060573.html
Copyright © 2020-2023  润新知