Unity精华☀️三、四元数(Quaternion)解决万向锁

本文涉及的产品
智能开放搜索 OpenSearch行业算法版,1GB 20LCU 1个月
实时计算 Flink 版,5000CU*H 3个月
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
简介: Unity精华☀️三、四元数(Quaternion)解决万向锁

本节为Unity万向锁系列的最后一节,

这一节我们就来解决这个难题:使用四元数旋转,避免Unity万向锁。

🟥 欧拉旋转 与 四元数旋转的对比

1️⃣ 欧拉旋转

代码示例:

    private void Update()
    {
        transform.eulerAngles+=new Vector3(1,1,1);
    }

优点:

  • 很容易理解,形象直观;
  • 表示更方便,只需要3个值(分别对应x、y、z轴的旋转角度);但按我的理解,它还是转换到了3个3*3的矩阵做变换,效率不如四元数;

缺点:

  • 之前提到过这种方法是要按照一个固定的坐标轴的顺序旋转的,因此不同的顺序会造成不同的结果;
  • 会造成万向节锁(Gimbal Lock)的现象。这种现象的发生就是由于上述固定坐标轴旋转顺序造成的。理论上,欧拉旋转可以靠这种顺序让一个物体指到任何一个想要的方向,但如果在旋转中不幸让某些坐标轴重合了就会发生万向节锁,这时就会丢失一个方向上的旋转能力,也就是说在这种状态下我们无论怎么旋转(当然还是要原先的顺序)都不可能得到某些想要的旋转效果,除非我们打破原先的旋转顺序或者同时旋转3个坐标轴;
  • 由于万向节锁的存在,欧拉旋转无法实现球面平滑插值;
想要的运动 遇到万向锁,欧拉角无法差值运算

代码:

        if (Input.GetKeyDown(KeyCode.C))
        {
            transform.localEulerAngles=Vector3.zero;
            transform.DOLocalRotate(new Vector3(90, 90, 90), 0.5f);
        }

2️⃣ 四元数旋转

优点:

  • 可以避免万向节锁现象;
  • 只需要一个4维的四元数就可以执行绕任意过原点的向量的旋转,方便快捷,在某些实现下比旋转矩阵效率更高;
  • 可以提供平滑插值;
四元数遇到万向锁可提供平滑的差值运算

代码:

        if (Input.GetKeyDown(KeyCode.C))
        {
            transform.localEulerAngles = Vector3.zero;
            transform.DOLocalRotateQuaternion(Quaternion.Euler(new Vector3(90, 90, 90)), 0.5f);
            //或者:
            transform.Rotate(new Vector3(0, 90, 0));
        }

缺点:

  • 比欧拉旋转稍微复杂了一点点,因为多了一个维度;
  • 理解更困难,不直观;

🟧 四元数旋转方法

1️⃣ Dotween,插值到目标欧拉角

Dotween的四元数旋转,是先将要旋转到的目标欧拉角,转化为四元数,

再进行旋转。

举例:

transform.DOLocalRotateQuaternion(Quaternion.Euler(new Vector3(90, 90, 90)), 0.5f);

2️⃣ Quaternion.Slerp,插值到目标欧拉角

先将欧拉角转化为四元数,

再插值运算到目标欧拉角。

    public float rotateSpeed = 2f;
    Quaternion targetAngels;
 
    private void Start()
    {
        targetAngels = Quaternion.Euler(0, 90f, 0);
    }
 
    void Update()
    {
        //  用 slerp 进行插值平滑的旋转
        transform.rotation = Quaternion.Slerp(transform.rotation, targetAngels, rotateSpeed * Time.deltaTime);
        // 当初始角度跟目标角度小于1,将目标角度赋值给初始角度,让旋转角度是我们需要的角度
        if (Quaternion.Angle(targetAngels, transform.rotation) < 1)
        {
            transform.rotation = targetAngels;
        }
    }

3️⃣ Rotate,绕自身坐标系旋转

将物体,绕自身的动态坐标系,旋转x角度。

举例:

transform.Rotate(new Vector3(0, 90, 0));
//或者:
transform.Rotate(0, 90, 0, Space.Self);
//或者:
transform.Rotate(new Vector3(0, 90, 0), Space.Self);

4️⃣ Rotate,绕世界坐标系旋转

将物体,绕世界的静态坐标系,旋转x角度。

举例:

transform.Rotate(90, 0, 0, Space.World);
//或者:
transform.Rotate(new Vector3(0, 90, 0), Space.World);

🟨 四元数和欧拉角的相互转换

1️⃣ 四元数转化成欧拉角

Vector3 v3=transform.rotation.eulerAngles;

2️⃣ 欧拉角转换成四元数

Quaternion rotation = Quaternion.Euler(v3);


相关文章
|
2月前
|
存储 API 图形学
Unity精华☀️二、到底是什么原因导致“万向锁”?旋转翻车的终极解析!
Unity精华☀️二、到底是什么原因导致“万向锁”?旋转翻车的终极解析!
|
2月前
|
图形学
Unity精华☀️一、从旋转到万向锁之:Unity的旋转
Unity精华☀️一、从旋转到万向锁之:Unity的旋转
|
C++
你们想要的开源的冰墩墩模型来了!! 先睹为快!实现冰墩墩自由!
你们想要的开源的冰墩墩模型来了!! 先睹为快!实现冰墩墩自由!
145 0
|
存储 算法 Linux
宿友用一把王者的时间入门了【二叉树】,你又懂多少呢?乌拉~~
宿友用一把王者的时间入门了【二叉树】,你又懂多少呢?乌拉~~
136 0
宿友用一把王者的时间入门了【二叉树】,你又懂多少呢?乌拉~~
|
存储 编解码 小程序
Unity面试题——图形学相关
Unity面试题——图形学相关
441 0
|
前端开发 JavaScript API
贝塞尔曲线在前端,走近她,然后爱上她
今天我们聊聊我们经常用的CSS3动画里面的贝尔赛曲线,希望能做到,她认识你,你也熟悉她! 本文源码: Bezier 看完你就懂了一半,动手你就成功了另外一半!
257 0
贝塞尔曲线在前端,走近她,然后爱上她
|
存储 算法 搜索推荐
高频算法题冒险之旅精讲(一)之LeetCode小牛试刀五道题
高频算法题冒险之旅精讲(一)之LeetCode小牛试刀五道题
131 0
高频算法题冒险之旅精讲(一)之LeetCode小牛试刀五道题
|
Java 开发者 iOS开发
“直线、分叉、圆圈”--程序逻辑之争 | 带你学《Java编程入门》之五
程序之所以能够按照人们的意愿执行,主要依靠的就是程序的控制结果。本章重点介绍选择与循环结构语句,学习如何利用这些不同的结构编写出有趣的程序,让程序的编写更灵活,操控更方便。
带你读《流动的色彩—— 一本探索自由水彩世界的技法书》之二:绘画技法
水彩画清新透明的质感、水色交融的画面,如同抒情诗或轻音乐般柔美。本书是一本从入门到精通式的水彩画技法教程,内容全面实用,讲解浅显易懂,编排清晰直观,既适合初学者,也适合有一定基础的绘画爱好者。希望本书能让读者在学习的过程中感受用画笔记录身边美好事物的乐趣。
下一篇
无影云桌面