欧拉旋转

 

在文章开头关于欧拉旋转的细节没有解释的太清楚,而又有不少人询问相关问题,我尽量把自己的理解写到这里,如有不对还望指出。

 

 

欧拉旋转是怎么运作的

 

 

欧拉旋转是我们最容易理解的一种旋转方式。以我们生活中为例,一个舞蹈老师告诉我们,完成某个舞蹈动作需要先向你的左边转30°,再向左侧弯腰60°,再起身向后弯腰90°(如果你能办到的话)。上面这样一个旋转的过程其实和我们在三维中进行欧拉旋转很类似,即我们是通过指明绕三个轴旋转的角度来进行旋转的,不同的是,日常生活中我们更愿意叫这些轴为前后左右上下。而这也意味着我们需要指明一个旋转顺序。这是因为,先绕X轴旋转90°、再绕Y轴30°和先绕Y轴旋转90°、再绕X轴30°得到的是不同的结果。

 

在Unity里,欧拉旋转的旋转顺序是Z、X、Y,这在相关的API文档中都有说明,例如 Transform.Rotate。其实文档中说得不是非常详细,还有一个细节我们需要明白。如果你仔细想想,就会发现有一个非常重要的东西我们没有说明白,那就是旋转时使用的坐标系。给定一个旋转顺序(例如这里的Z、X、Y),以及它们对应的旋转角度(α,β,r),有两种坐标系可以选择:

  1. 绕坐标系E下的Z轴旋转α,绕坐标系E下的Y轴旋转β,绕坐标系E下的X轴旋转r,即进行一次旋转时不一起旋转当前坐标系;
  2. 绕坐标系E下的Z轴旋转α,绕坐标系E在绕Z轴旋转α后的新坐标系E'下的Y轴旋转β,绕坐标系E'在绕Y轴旋转β后的新坐标系E''下的X轴旋转r, 即在旋转时,把坐标系一起转动;

 

很容易知道,这两种选择的结果是不一样的。但如果把它们的旋转顺序颠倒一下,其实结果就会一样。说得明白点,在第一种情况下、按ZXY顺序旋转和在第二种情况下、按YXZ顺序旋转是一样的。证明方法可以看下 这篇文章。而Unity文档中说明的旋转顺序指的是在第一种情况下的顺序。

 

如果你还是不懂这意味着什么,可以试着调用下这个函数。例如,你认为下面代码的结果是什么:

[csharp]  
      print? 
     
   
1. transform.Rotate(new Vector3(0, 30, 90));

原模型的方向和执行结果如下:

unity物体绕自己的z轴不停旋转 unity让物体绕y轴旋转30度_坐标轴

 

unity物体绕自己的z轴不停旋转 unity让物体绕y轴旋转30度_unity物体绕自己的z轴不停旋转_02

 

 

 

而我们可以再分别执行下面的代码:

[csharp] 
       print?         
1. // First case  
2. new Vector3(0, 30, 0));  
3. new Vector3(0, 0, 90));  
4.   
5. // Second case  
6. //      transform.Rotate(new Vector3(0, 0, 90));  
7. //      transform.Rotate(new Vector3(0, 30, 0));

两种情况的结果分别是:

unity物体绕自己的z轴不停旋转 unity让物体绕y轴旋转30度_坐标轴_03

 

unity物体绕自己的z轴不停旋转 unity让物体绕y轴旋转30度_旋转角度_04

 

可以发现,调用transform.Rotate(new Vector3(0, 30, 90));是和第一种情况中的代码是一样的结果,即先旋转Y、再旋转Z。进一步实验,我们会发现transform.Rotate(new Vector3(30, 90, -40));的结果是和transform.Rotate(new Vector3(0, 90, 0));transform.Rotate(new Vector3(30, 0, 0));transform.Rotate(new Vector3(0, 0, -40));的结果一样的。你会问了,文档中不是明明说了旋转顺序是Z、X、Y吗?怎么现在完全反过来了呢?原因就是我们之前说的两种坐标系的选择。在一次调用transform.Rotate的过程中,坐标轴是不随每次单个坐标轴的旋转而旋转的。而在调用transform.Rotate后,这个旋转坐标系才会变化。也就是说,transform.Rotate(new Vector3(30, 90, -40));执行时使用的是第一种情况,而transform.Rotate(new Vector3(0, 90, 0));transform.Rotate(new Vector3(30, 0, 0));transform.Rotate(new Vector3(0, 0, -40));每一句则是分别使用了上一句执行后的坐标系,即第二种坐标系情况。因此,我们看起来顺序好像是完全是反了,但结果是一样的。