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

0 引言

在我的上一篇笔记中,我主要关注点在“什么是万向节和万向节锁”上,另外简单说了说欧拉角会按照万向节的规则运行。但对于“欧拉角为什么会按照万向节这一(相对)复杂规则来确定旋转值”没有讨论。本篇文章,就来谈谈我对欧拉角为什么会符合万向节规则的理解。本文使用的欧拉角的定义是我为了清晰易懂从而根据自己的理解描述的(可能不准确)。

1 什么是欧拉角

1.1 我的理解:

欧拉角就是用来描述物体从一个初始方向,依靠围绕已知的一个固定的坐标系的三个轴进行一定次序的旋转,而让物体变为目标方向的三个旋转值。

以物体的z轴正方向为例(描述欧拉角和方向均按(x,y,z)的顺序):初始方向为(0,0,1),坐标系采用物体惯性坐标系,采用欧拉角(90,0,0)旋转后(即物体绕物体惯性坐标系X轴旋转90°,绕y,z旋转0),物体的z轴正方向变为(0,-1,0)。

旋转前后 描述
初始状态下(欧拉角为(0,0,0)),物体正方向为蓝色长方体指向方向
物体绕X轴(红色箭头)旋转90°后(即物体欧拉角(90,0,0)),物体正方向变为朝下

所以欧拉角要确定四个东西:初始方向坐标系目标方向(或者说各轴旋转度数)以及旋转次序

1.2 旋转顺序

欧拉角的旋转是按照确定的旋转顺序进行的(比如先绕Z轴旋转,再绕X轴旋转,最后绕Y轴旋转),而不是让物体绕三个轴同时进行旋转。在不同的研究领域当中,研究者会采用不同的旋转顺序。

在Unity当中,欧拉角的旋转顺序是ZXY,即先绕Z旋转,再绕X旋转,最后绕Y旋转。我们并不能看到这三个旋转步骤的过程,我们只能看到完成三个旋转步骤之后的结果。也就是说每次修改了X、Y、Z中一个(不管是不是按顺序修改的),Unity都会从Z-X-Y的顺序计算出物体当前正确的朝向,而我们能看到的就是最后计算完成朝向的物体。

2 欧拉角和万向节的关系

在我的前一篇笔记当中,我是这样说的:

欧拉角内部就是使用的万向节的规则。可以想象成每个游戏物体有一个隐藏的万向节坐标系统(当然,这是不准确的,这里这么说只是为了帮助理解),就像上面图上的飞机一样。而Inspector面板上的rotation就是欧拉角,也就是采用的万向节的规则。

这句话的重点在于第一句:欧拉角内部就是使用的万向节的规则。所以欧拉角除了会按照一定次序进行旋转外,还会特意去考虑按照万向节的规则来进行旋转?不对! 那句话的出现只是为了方便当时情境的理解,万向节的规则之所以出现在欧拉角中,并不是因为欧拉角本身定义了这套规则。而是:万向节规则是欧拉角这条“按一定次序进行旋转”定义的副作用

但是这么说的话。。。好像有点问题啊。
1.首先,欧拉角绕轴旋转的三个轴是固定的,但是万向节的三个轴不是固定的,万向节的一个轴会随另一个轴的旋转而旋转。
2.其次,既然前面说过了Unity会按照Z、X、Y的顺序旋转,根据万向节的规则进行ZXY顺序的旋转不应该会出现万向锁啊?

3 化抽象为具体

首先要说明的是,Inspector面板上的欧拉角参考的坐标系是物体的惯性坐标系或者局部坐标系。为什么是"或者"?因为初始状态下(0,0,0)物体的惯性坐标系和局部坐标系是重合的。对于局部坐标系,在物体旋转时,局部坐标系会随物体旋转而旋转,但是这并不影响,因为欧拉角采用的是物体在进行欧拉旋转前的局部坐标系(即旋转完Z轴后,该绕Y轴旋转了,依然绕的是旋转Z轴前的那个Y轴(那个和惯性坐标系重合时的Y轴))。

3.1 Z轴

现在我们先从Z轴开始分析。在旋转Z轴前,我添加了一个蓝色长方体用于标注当前旋转使用的Z轴。然后我开始调整Inspector面板上z的值(即让物体绕Z轴旋转)。

按照欧拉角定义,每次z的数值改变一次,就会按z、x、y的顺序计算物体的旋转,而在这里我是连续更改z的数值,也就意味着Unity会不断地按“先让物体绕Z轴旋转z°,再绕X轴旋转0°,最后绕Y轴旋转0°”的方式更新物体当前朝向。

3.2 X轴

3.2.1 确定X轴

我将Inspector面板上的z轴设置成60°,即让物体绕Z轴旋转60°。然后想看看再调整Inspector面板上的x值是什么效果(也就是让物体绕X轴旋转),但在旋转之前,我依然想添加一个红色长方体用于标注当前旋转使用的X轴了。那么问题就来了,我应该把这个长方体放在哪?

前面提到过Inpsector面板上参考的是惯性坐标系或者旋转开始前的局部坐标系,所以这个红色的长方体应当与惯性坐标系X轴重合。这里就有一个需要重点关注的点:也就是说,物体绕Z轴旋转后,不会对X轴的位置造成影响。

3.2.2 绕X轴旋转

现在动态地调整Inspector面板上x的值,可以看到物体像预期那样绕惯性坐标系X轴进行旋转。同时也能看到蓝色的长方体因为绑定到了物体上,与物体保持相对静止。

3D视角 侧视图

按照欧拉角定义,每次x的数值改变一次,就会按z、x、y的顺序计算物体的旋转,而在这里我是连续更改x的数值,也就意味着Unity会不断地按“先让物体绕Z轴旋转60°,再绕X轴旋转x°,最后绕Y轴旋转0°”的方式更新物体当前朝向。

3.2.3 绕Z轴旋转

现在将x的值设为45°。如果此时我修改z的值会出现什么情况?按照之前所说的,修改z的值应当是绕惯性坐标系的z轴进行旋转。动手试试却发现:

物体是绕蓝色长方体进行旋转。我在上面一直强调的是欧拉角的旋转顺序,这也是出现现在这种情况的原因,当前修改z值和前面修改z值是有区别的,现在x的值不再为0了。当我修改inspector面板上z值时,Unity会根据欧拉角规则“先让物体绕Z轴旋转z°,然后绕X轴旋转45°,最后绕Y轴旋转0°”设置物体的朝向。但是我们是无法看到”先Z,然后X,最后Y“这个旋转过程,我们能看到的是已经旋转完的物体。举个可能不完全准确的例子,在我连续修改z值时:
Inspector面板(x,y,z)
第1帧(45,60,0):我们看到的物体 是已经完成“绕Z轴旋转60°,绕X轴旋转45°,绕Y轴旋转0°”的物体
第2帧(45,61,0):我们看到的物体 是已经完成“绕Z轴旋转61°,绕X轴旋转45°,绕Y轴旋转0°”的物体
第3帧(45,62,0):我们看到的物体 是已经完成“绕Z轴旋转62°,绕X轴旋转45°,绕Y轴旋转0°”的物体

所以不管如何旋转,总是先进行绕Z轴的旋转,所以Z轴总是和初始状态(0,0,0)的物体保持相对静止的,而蓝色长方体最开始是指示Z轴的方向的。只不过绕X轴旋转比绕Z轴旋转后进行,蓝色长方体与物体保持相对静止,随着物体绕X轴旋转而旋转。

也就是说,蓝色长方体始终与物体保持相对静止,始终指示着物体的旋转轴Z轴。所以当修改z值是,尽管物体看起来不是绕惯性坐标系Z轴进行的旋转,但实质上它是绕惯性坐标系Z轴进行的。此时只有x的值在变化,所以只会产生绕X轴的旋转,直观上看起来就像是绕当前蓝色长方体进行旋转。(表达能力比较差,不知道说明白没有)。

这里就和万向节系统中的Z轴和X轴的关系一样了:Z轴的旋转不影响X轴的方位,但Z轴会随着X轴的旋转而旋转且与物体保持相对静止(直观上)。(当然,这只是因为旋转顺序导致看起来是这样的,但物体绕Z轴旋转时,始终是绕惯性坐标轴Z轴)

3.3 Y轴

3.3.1确定Y轴

现在inspector面板上x,y,z的值分别是45,0,60。现在我想试着旋转Y轴,但是在旋转之前,我想用一个绿色长方体标注物体旋转所绕的Y轴。按照前面的思路,无论是绕X轴旋转还是绕Z轴旋转,物体修改y值时绕的仍然是惯性坐标系Y轴,所以绿色长方体应当与惯性坐标系Y轴重合(与初始状态(0,0,0)时的局部坐标系Y轴重合)。

3.3.2 绕Y轴旋转

现在动态地调整Inspector面板上y的值,可以看到物体像预期那样绕惯性坐标系Y轴进行旋转。同时也能看到蓝色长方体和红色长方体因为绑定到了物体上,与物体保持相对静止。

按照欧拉角定义,每次y的数值改变一次,就会按z、x、y的顺序计算物体的旋转,而在这里我是连续更改y的数值,也就意味着Unity会不断地按“先让物体绕Z轴旋转60°,再绕X轴旋转45°,最后绕Y轴旋转y°”的方式更新物体当前朝向。

3.3.3 绕Z轴旋转

现在将y的值设为30°,即(x,y,z)=(45,30,60)。如果此时我修改z的值会出现什么情况?和前面的理论一样,物体依然绕蓝色长方体旋转。

3.3.4 绕X轴旋转

依然设(x,y,z)=(45,30,60),和前面理论类似,此时修改x的值,物体将会绕红色长方体旋转。

我们来理一下,为什么在这时修改x的值,物体依然绕红色长方体旋转。

当每次修改x的值时,Unity都会按照“先让物体绕Z轴旋转60°,再让物体绕X轴旋转x°,最后让物体绕Y轴旋转30°”的顺序确定每一帧物体的朝向。所以Unity计算绕X轴旋转时,围绕的轴是绕Z轴旋转之后、绕Y轴旋转之前的X轴(因为先绕X轴旋转,再绕Y轴旋转),即物体的惯性坐标系X轴,也就是红色长方体标记的轴向。

那么为什么此时物体不再绕惯性坐标系X轴旋转,而是绕红色长方体旋转呢?

在Unity内部,绕X旋转在绕Y轴旋转之前,此时相当于物体不绕Y轴旋转(只绕Z和X旋转),此时红色长方体始终与惯性坐标轴X轴重合,也就是指明了物体的旋转轴X轴。当绕Y轴进行旋转后,物体朝向发生变化,但是红色长方体始终标明了物体绕X轴旋转的方向。

因此无论何时修改x的值,我们直观上看起来物体就是绕当前的红色长方体进行的旋转。

小总结:这里可以看出,Y轴与(X轴、Z轴)的关系也和万向节一样。X、Z轴的旋转不会影响Y轴的方位,但是Y轴的旋转会影响X、Z轴的方位。

4 解决疑惑

但是这么说的话。。。好像有点问题啊。
1.首先,欧拉角绕轴旋转的三个轴是固定的,但是万向节的三个轴不是固定的,万向节的一个轴会随另一个轴的旋转而旋转。
2.其次,既然前面说过了Unity会按照Z、X、Y的顺序旋转,根据万向节的规则进行ZXY顺序的旋转不应该会出现万向锁啊?

  1. 确实,物体始终绕的是一个固定的坐标系即固定的三个轴进行旋转。但经过前面的理论推导,与我们直觉上不同地是,直观上一个轴的旋转会影响另一个轴(只是看起来)。
    2.正如1所说,直观上一个轴确实会影响另一个周的旋转,从而出现万向锁。

5 总结

因为我的想法过于抽象,以我的表达能力似乎挺难清晰地表达出来,罗里吧嗦说了那么多,希望能够大概表达出我的想法。

最后做个总结,根据上面的推论,欧拉角之所以会遵守万向节规则,就是因为欧拉角定义要按顺序绕三个轴旋转。
当绕X轴旋转时,物体的角度肯定发生了变化,但是物体相对于Z轴的角度没有发生变化。
当绕Y轴旋转时,物体的角度也肯定发生了变化,但是物体相对于Z轴和X轴的角度没有发生变化。

让物体绕按顺序绕三个轴进行旋转,就会导致修改物体的旋转分量x、y、z时,直观上看起来物体是按照万向节进行的,也就会出现万向节锁的情况。

如果之后发现有什么更方便解释我的想法的方法,我会修改此篇文章笔记。

【Unity学习笔记】为什么欧拉角(Euler)会符合万向节(Gimbal)规则?相关推荐

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

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

  2. 【Unity学习笔记】[Unity中文课堂教程] C#中级编程代码

    [Unity学习笔记][Unity中文课堂教程] C#中级编程代码 最近想补一补C#基础,Unity官方的C#中级编程教程质量很高,于是开个帖子把跟着敲+记录了部分价讲解和我自己的理解的代码存在这 原 ...

  3. Unity学习笔记:Unity 3D 飞机大战

    Unity学习笔记:Unity 3D 飞机大战 1.打开unity软件后,首先新建Quad作为背景,导入飞机模型,并为其添加刚体 然后创建C#脚本,挂载到飞机上. 2.给飞机创建子弹,让子弹成为预制体 ...

  4. Unity学习笔记—二次元日系游戏制作(实践篇-游戏初始化场景制作)

    原教程:siki:二次元日系游戏制作工具 - live2dSDK入门教程 http://www.sikiedu.com/my/course/282 (上)Unity学习笔记-二次元日系游戏制作(理论篇 ...

  5. Unity学习笔记--赛车的控制代码

    Unity学习笔记–赛车的控制代码 using System.Collections; using System.Collections.Generic; using UnityEngine;publ ...

  6. Unity学习笔记(4)-----粒子效果的实现

    Unity学习笔记(4)-–粒子效果的实现 一.效果展示 下面用若干张张动图展示效果: 大概就是这样,并不是很难. 实际效果要比图中的好一点(顺畅得多). 实现步骤 大致可以分为如下几个步骤,然后逐个 ...

  7. Unity学习笔记1 简易2D横版RPG游戏制作(一)

    这个教程是参考一个YouTube上面的教程做的,原作者的教程做得比较简单,我先参考着做一遍,毕竟我也只是个初学者,还没办法完全自制哈哈.不过我之前也看过一个2D平台游戏的系列教程了,以后会整合起来,做 ...

  8. Unity学习笔记:个人学习项目《疯狂天才埃德加》纠错文档

    Unity学习笔记:个人学习项目<疯狂天才埃德加>纠错文档 本文档是完成学校Unity课程作业时建立的纠错文档.用于记录自己开发过程中遇到的各种问题,以便下次遇到相同的问题时及时找到解决方 ...

  9. 【Unity学习笔记】UnrealToUnity教程:(网上购买的素材导入Unreal+插件转Unity)

    [Unity学习笔记]UnrealToUnity教程: 最近想从Unreal那边化点缘借借素材,没想到踩到一个大坑 一,素材导入Unreal 这个教程比较多,根据素材的来源,传送门是以下这几个: 1. ...

最新文章

  1. 提升ListView的运行效率
  2. 深入理解多线程(五)—— Java虚拟机的锁优化技术
  3. GraphQL:Descriptor Attributes
  4. 数据结构之栈与递归的应用(全排列递归解法)
  5. 调研报告|在线语音识别改进之 RNN-T 训练
  6. @Resource和@Autowired小笔记
  7. BZOJ4141 THUSC2013 魔塔 贪心
  8. 数据结构与算法学习笔记
  9. WiFi 模块AT指令集整理
  10. 服务器虚拟机解锁苹果,Unlocker(VMware虚拟机MacOS系统解锁工具)v3.0.2 免费版-ucbug软件站...
  11. 单片机 舵机 SG90 舵机 控制原理 MSP432 单片机
  12. 敏捷技术和管理方法思考列表---长期维护
  13. [转]多普达818、828+升级中文WM6.1及必装软件全过程讲解
  14. 启用计算机无线网络连接,无线网络连接未启用DHCP是怎么回事?如何解决?
  15. cmd设置总是置顶_怎么将想要的窗口一直置顶 原来只要这简单的一步
  16. H5实现拨打电话功能
  17. 体外诊断(POCT)之检测卡配置文件
  18. 解决企业数字化“历史遗留问题”,低代码具备天然优势 | 专访腾讯云微搭骆勤
  19. FCKeditor爆绝对路径
  20. 分享嵌入式入门学习指导

热门文章

  1. solidity合约访问其他合约的mapping
  2. winform实现发票打印功能
  3. Git HEAD及detached head
  4. 《欢乐坦克大战》微信小游戏开发总结
  5. 前端请柬框架_女儿满月请柬正确的书写格式
  6. fastboot出现错误:no permissions fastboot
  7. 解决hotmail无法登陆的问题
  8. 【自然语言处理】【大模型】Chinchilla:训练计算利用率最优的大语言模型
  9. 获取application.yml配置文件中配置的对象集合
  10. statement和prepareStatement的区别