【Unity学习笔记】Unity中的欧拉角(Euler Angle)和万向节(Gimbal)

声明:此篇文章是个人学习笔记,并非教程,所以内容可能不够严谨。可作参考,但不保证绝对正确。如果你发现我的文章有什么错误,非常欢迎指正,谢谢哦。

目录

  • 1 奇怪的现象
    • 1.2现象一
    • 1.2 现象二
    • 1.3 现象三
  • 2 万向节(Gimbal)和万向节锁(Gimbal Lock)
    • 2.1 万向节
    • 2.2 欧拉角和万向节的关系
    • 2.3 万向节锁
      • 2.3.1 什么是万向节锁
      • 2.3.2 如何避免万向节锁
  • 3 解释奇怪的现象
    • 3.1 现象一
    • 3.2 现象二
    • 3.3 现象三
    • 3.4 补充现象四
    • 3.5 补充现象五
  • 4 总结
    • 4.1 rotation值的含义
    • 4.2不同的万向节示例图
      • 第一种图示
      • 第二种图示
      • 相同点
    • 4.3最后
  • 5 推荐文章

1 奇怪的现象

Unity的Inspector面板上的rotation是欧拉角,简单来说欧拉角由三个旋转值组成。当刚开始接触Unity时,在Inspector面板上看到Transform组件,会想当然的认为它的rotation要么是指物体绕其惯性坐标轴的旋转度数,要么是物体绕其局部坐标轴的旋转度数。简简单单,X分量就是绕X轴,Y分量就是绕Y轴,Z分量就是绕Z轴而已嘛。

但是当我们试着调整Inspector面板上的rotation时,有时候又会出现奇怪的现象。

1.2现象一

物体旋转既不是绕自身坐标轴旋转,也不是绕惯性坐标轴旋转。

显示的自身坐标轴 显示的惯性坐标轴 Inspector面板
【Unity学习笔记】Unity中的欧拉角(Euler Angle)和万向节(Gimbal)_第1张图片 【Unity学习笔记】Unity中的欧拉角(Euler Angle)和万向节(Gimbal)_第2张图片 【Unity学习笔记】Unity中的欧拉角(Euler Angle)和万向节(Gimbal)_第3张图片

1.2 现象二

有时候,我们直接在场景中调整物体的单个旋转轴(无论惯性坐标轴还是自身坐标轴),但在Inspector面板上却能看到rotation三个数值在同时变化。

场景 Inspector面板
【Unity学习笔记】Unity中的欧拉角(Euler Angle)和万向节(Gimbal)_第4张图片 【Unity学习笔记】Unity中的欧拉角(Euler Angle)和万向节(Gimbal)_第5张图片

1.3 现象三

更严重的是,有时候会出现一个旋转方向丢失的现象,比如当我们将X旋转90°,再去调整Z和Y的值时会发现:调整Z和Y的效果一样,也就是说我们三个旋转方向变两个了。

将X旋转至90°,再旋转Z轴 将X旋转至90°,再旋转Y轴
【Unity学习笔记】Unity中的欧拉角(Euler Angle)和万向节(Gimbal)_第6张图片

为什么会出现这些奇怪的现象,难道是因为Unity出了什么Bug?在解决这个问题之前,先要了解一下万向节。

2 万向节(Gimbal)和万向节锁(Gimbal Lock)

2.1 万向节

如果以前没有了解过万向节,可以看这里:万向节和万向节锁

万向节有三个坐标轴X,Y,Z,刚开始时,三个坐标轴是相互垂直的,这似乎很常见。

但要注意的一点是,它的三个坐标轴有父子关系,父轴的转动会带动子轴的转动,类似于我们在Unity的Hierachy面板上构建的父子关系(如下图)。试着排列三个坐标轴的父子关系,会发现三个轴的父子关系有6种,xyz\xzy\yxz\yzx\zxy\zyx,在不同的应用场景中,人们会采用不同的关系。下面以yxz为例子:
轴与轴的父子关系示例
现在假设三个轴的层次关系是这样的: Z在最底层,X是Z的父项,Y是X的父项。也就是说,当我们旋转万向节中的三个轴时,会有以下现象:
Z轴旋转时,另外两个轴不旋转
X轴旋转时,Z轴随X轴旋转而旋转(相对静止),Y轴不动
Y轴旋转时,X,Z都随Y轴旋转而旋转(相对静止)
文字性的描述可能不够清晰,下面的图来自我自己在Unity中编写的万向节模拟系统,物体的旋转使用万向节来实现(其中蓝色的环表示物体的Z旋转轴,红色表示X,绿色表示Y):

旋转的轴 图片 描述
Z 【Unity学习笔记】Unity中的欧拉角(Euler Angle)和万向节(Gimbal)_第7张图片 蓝色的轴是Z轴,当旋转Z轴时,X和Y轴保持原有状态不动。因为Z轴在最底层。
X 【Unity学习笔记】Unity中的欧拉角(Euler Angle)和万向节(Gimbal)_第8张图片 红色的轴是X轴,因为Z轴是X轴的子项,所以当旋转X轴时,Z轴会随之运动(保持相对静止)。而Y轴保持不动
Y 【Unity学习笔记】Unity中的欧拉角(Euler Angle)和万向节(Gimbal)_第9张图片 绿色的轴是Y轴,因为X轴是Y轴的子项,而Z轴是Y轴子项的子项,所以旋转Y轴时,X和Z均会随之旋转从而与Y轴保持相对静止

2.2 欧拉角和万向节的关系

欧拉角内部就是使用的万向节的规则(为什么使用这种规则,为什么不采用三个轴互不影响的策略,可以考虑参考我的下一篇笔记)。可以想象成每个游戏物体有一个隐藏的万向节坐标系统(当然,这是不准确的,这里这么说只是为了帮助理解),就像上面图上的飞机一样。而Inspector面板上的rotation就是欧拉角,也就是采用的万向节的规则。

2.3 万向节锁

2.3.1 什么是万向节锁

万向节的特点是“轴与轴之间存在父子关系,每个轴对另外两个轴的影响各不相同”,也正是因为这个特点,导致出现了一些缺点。
比如当我们将X轴旋转90°后,Z轴和Y轴会变成平行状态,然后我们会发现旋转Z轴和Y轴的效果竟然是一模一样的,这就导致当我们想让图中的飞机实现转向操作时就找不到轴了(这似乎与我们的直觉相违背,三个轴变成了两个)

将X轴旋转90° 旋转Z和Y对物体的旋转效果一样 利用万向节中的轴无法完成的旋转
【Unity学习笔记】Unity中的欧拉角(Euler Angle)和万向节(Gimbal)_第10张图片 【Unity学习笔记】Unity中的欧拉角(Euler Angle)和万向节(Gimbal)_第11张图片 【Unity学习笔记】Unity中的欧拉角(Euler Angle)和万向节(Gimbal)_第12张图片

2.3.2 如何避免万向节锁

3 解释奇怪的现象

前面提到,欧拉角运用的就是万向节的规则。经过我的实验证明,Unity中的欧拉角采用的是yxz的层次关系(即y在最外层,如上面的例子),Inspector面板上显示的并不是物体绕自身局部坐标轴旋转的度数,也不是绕惯性坐标轴旋转的度数,而是隐藏的万向节旋转轴旋转的度数。那么一切都说得通了,真相只有一个!

3.1 现象一

物体旋转既不是绕自身坐标轴旋转,也不是饶世界坐标轴旋转。

解释:这是因为物体绕得是万向节的三个轴,既不同于Unity物体自身坐标轴也不同于惯性坐标轴。

3.2 现象二

有时候,我们直接在场景中调整物体的单个旋转轴(无论惯性坐标轴还是自身坐标轴),但在Inspector面板上却能看到rotation三个数值在同时变化。

场景中的旋转轴要么是使用的物体局部坐标系,要么使用的是惯性坐标系,这二者与物体的万向节坐标系不同。当使用场景中的旋转轴进行旋转时,Unity内部应该是使用的四元数进行处理,然后将其转换为欧拉角(万向节坐标系)的结果显示在Inspector面板上。等价转换之后,可能旋转场景中一个轴的效果需要动用欧拉角的三个轴。

3.3 现象三

更严重的是,有时候会出现一个旋转方向丢失的现象,比如当我们将X旋转90°,再去调整Z和Y的值时会发现:调整Z和Y的效果一样,也就是说我们三个旋转方向变两个了。

这一现象已经在前面解释过了,物体隐含有一个万向节系统, 有些情况下就会出现万向节锁(Gimbal Lock)

3.4 补充现象四

当我们在Inspector面板上按照Z、X、Y的顺序调整rotation的值时会发现,此时场景中物体的旋转效果是绕着物体的惯性坐标轴进行旋转的。这是因为初始状态下(0,0,0),物体的万向节系统的三个轴是和物体的惯性坐标轴重合的,旋转Z轴不影响X,Y轴的位置和角度,所以旋转完Z轴后,X、Y轴依然与惯性坐标轴重合。

如果你发现结果和我说的不一样,可能要检查一下物体中心和坐标轴的设定是不是如此:在这里插入图片描述

3.5 补充现象五

当我们在Inspector面板上按照Y、X、Z的顺序调整rotation的值时会发现,此时场景中物体的旋转效果是绕着物体的局部坐标轴进行旋转的。这是因为初始状态下(0,0,0),物体的万向节系统的三个轴不仅是和物体的惯性坐标轴重合,也是和物体的局部坐标轴重合的。旋转Y轴时会带动X和Z轴旋转,三个轴保持相对静止,这和局部坐标轴是一样一样滴。

4 总结

4.1 rotation值的含义

最后再缕一缕关于Unity中欧拉角的思路。

欧拉角由三个旋转值组成,三个旋转值会根据万向节的规则确定。Unity中Inspector面板上的rotation的三个值对应的是物体的欧拉角,即通过万向节规则确定的三个旋转值。当我们调节Inspector面板上的rotation的值时,Unity根据万向节规则计算出物体当前的朝向。

4.2不同的万向节示例图

我在不同的文章或者视频中看到了两种万向节的示例图,第一次见感觉这两种万向节似乎相互矛盾,但二者其实本质上是一样的。

第一种图示

这张图示是我在维基百科英文版Wikipedia中看到的,它的旋转方式是让环绕着横插过环的轴进行旋转的。

第二种图示

这种图示是我在讲解万向节锁的视频中看到的,也是上面我自己做的图中采用的方式,即像轮胎一样沿着环进行旋转。这里就懒得放图了。

相同点

这两种不同的旋转方式并不影响它们表达相同的本质:父轴的旋转会带动子轴的旋转,而子轴的旋转并不带动父轴的旋转。
另外,我还在一些文章中看到了最里层的轴会带动外层的轴旋转,外层的轴不会带动里层的轴旋转(和上面相反),其本质也是一样一样滴。

4.3最后

这里Unity中关于欧拉角和万向节的讨论依然不够深入,停留在表面的理解上。我将在我的下一篇文章中说说我对“欧拉角为什么会符合万向节的规则”的理解。

5 推荐文章

①清晰易懂的万向节和万向锁的视频(前面已经提到): https://v.youku.com/v_show/id_XNjk1MTkzMTM2.html#paction

②大佬关于欧拉角的讲解文章:
Ⅰ.https://blog.csdn.net/andrewfan/article/details/60866636
Ⅱ.https://blog.csdn.net/AndrewFan/article/details/60981437#comments_14584533

你可能感兴趣的:(Unity学习笔记,unity)