阅读 196

Unity精华☀️(二)到底是什么原因导致“万向锁”?旋转翻车的终极解析!

Unity精华☀️(二)到底是什么原因导致“万向锁”?旋转翻车的终极解析!

哈喽大家好,你的橙哥突然出现~


本系列博客地址:传送门




前几天跟大家说,面试时尴尬的名场面,


结果收到很多小老弟的留言,说是被说中了心声,心疼这些小老弟们。


 


那今天呢,咱来就来盘一盘面试时经常会问的一个问题:


什么是万向锁?




 


一、万向锁现象

我们认为,改变欧拉角x值,物体会绕着自身x轴旋转,改变y值,会绕着y旋转,z值同理(x)


但在某些情况下,unity物体并不会按照这个来,它会丢失一个自由度,比如下面情况:

 


当X轴角度为±90°时,


此时只有Z值是沿着自身Z轴旋转,且Y值旋转方向跟也是Z轴,丢失Y轴旋转自由度。




 


还比如这位博主讲的,丢失了一个自由度:传送门


这样的旋转,如果用改变Transform欧拉角来旋转,不一写一个错么




万向锁用专业术语讲就是:


万向锁,是在使用动态欧拉角表示三维物体的旋转时出现的问题。


在物体旋转中,物体丢失了一个旋转维度。


理不理解不重要,别人问就这样说!


 


 


二、产生万向锁的应用场景

比如骰子游戏:


不断旋转骰子,总会有机会使骰子旋转到万向锁角度,失去一个方向的自由度(x为90度+2π倍,此时改变y、z值,旋转方向相同)


若此时再使用动态欧拉角进行失去自由度方向的旋转,则注定不会起作用了。




 


 


三、Inspector面板欧拉角的旋转

为了解面板欧拉角的旋转,首先要先了解几个基础知识:


1、世界坐标系,是静态欧拉角,是不会变化的


2、物体本身坐标系,是动态欧拉角,会随着物体转动而转动


3、Unity官方提醒:


要仅使用物体的欧拉角来读取角度,并将其设置为固定值。不要增加它们。


因为当角度超过360度时会失败。应使用Transform.Rotate来执行旋转操作。


此处“角度超过360度时会失败”的理解是,Unity内部使用四元数去执行旋转,不会存储欧拉角的累计值,欧拉角只代表了等值的旋转变化结果,当旋转角度X超过360度时,存储的角度为X-360,例如,361度等同于1度。


同时,Unity API提醒我们不要单独设置一个欧拉角的参数(例如,Eulerangles.x=10;),这将导致错误的旋转,应当同时对x、y、z三个参数进行设置。


 


那么我们改变Unity物体层级面板上的欧拉角值,


物体绕的是世界坐标系旋转,还是物体本身坐标系旋转呢?





我们来测试看看:


 


1、绘制世界坐标系

将下方脚本挂载在物体上,显示的就是不会变化的世界坐标系


方便我们观察。


using UnityEngine;

 

public class WorldCoordinateSystem : MonoBehaviour

{

    void OnDrawGizmos()

    {

        Gizmos.color = Color.red;

        Vector3 direction = Vector3.right * 2; //世界坐标系的 轴向x

        Gizmos.DrawRay(transform.position, direction);

        Gizmos.color = Color.green;

        direction = Vector3.up * 2; //世界坐标系的 轴向y

        Gizmos.DrawRay(transform.position, direction);

        Gizmos.color = Color.blue;

        direction = Vector3.forward * 2; //世界坐标系的 轴向z

        Gizmos.DrawRay(transform.position, direction);

    }

}

现在下方显示的绿的长线,为Y轴,红色x、蓝色z。




 


2、旋转测试

将模型调成Local模式,现在显示模型的自身坐标轴


将模型角度调成(45,45,45),方便我们测试观察:


   


 


好的,现在我们既能在视图中看到模型自身的坐标,也能看到不动的世界坐标。


现在就来转一下Inspector的欧拉角值,看看模型到底是绕着哪些轴旋转。


 


1、旋转Y轴


我们发现,旋转Y轴是绕着世界坐标系进行旋转的,并不是绕自身坐标系!




 


2、旋转x轴


为便于观察,将z值设为0。


我们发现:旋转x轴,是绕着自身坐标系旋转的,并不是绕着世界坐标系旋转!


现在就发现了,改变层级面板的值,竟然不是绕着同一个坐标系进行旋转?!




 


3、旋转z值


我们发现:旋转z值,是绕着自身坐标系旋转。




 


那我们现在来想一下:


如果绕着同一套坐标系旋转,肯定不会出现旋转面重合,共面现象


但绕着两套坐标轴旋转,肯定有机会出现旋转面共面情况,丢失一个旋转自由度啊!


 


丢失自由度后,可不就出现万向锁了么,怎么转都不按想要的方向来了。




 


有的小老弟可能用的不是上述角度,发现并不是按照上面说的轴旋转,那这是怎么回事呢?


首先了解:


unity 3D欧拉角的旋转顺序是:z-x-y


就是说,你所做的任何旋转,都受前面的角度影响。


比如你修改了Z值,那现在调整X值,肯定不会绕着自身坐标系x轴旋转。


但你新建一个父物体,将z值角度给父物体,自身z值为0,再旋转一下x,是不是就像预期一样啦?


 


 


四、自由度是怎样丢失的?

上面我们提到了,Unity的旋转顺序是:z-x-y,


这叫做Unity的顺归:传送门


 


物体旋转(x,y,z)度,是先旋转z轴,再旋转x轴,最后y轴。


那么,当x为90度时,物体z轴与世界坐标y轴同线,


y轴绕着世界坐标系y轴旋转,z轴绕着自身坐标系z轴旋转,一切都没问题,


但不管旋转y还是z,会发现只在一个平面上进行旋转,现在丢失了一个旋转方向,产生了万向锁。




 


若此时用 transform.localEulerAngles 去控制物体旋转,改变的是层级面板上的值,是无法转到想要的角度的


这也是 transform.localEulerAngles 控制骰子旋转,无法达到想要的角度的问题原因。


 


下一节,我们开始讲解怎样解决万向锁的四元数!


国际惯例,一键三连走一波~




 


如果你有技术上的问题或困扰


可以随时给我发私信


和我聊一聊你的困扰????

————————————————

版权声明:本文为CSDN博主「橙子SKODE」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/weixin_38239050/article/details/115391302


文章分类
后端
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐