随笔 - 167  文章 - 2  评论 - 38  阅读 - 37万

Unity在旋转时出现万向节锁的解决方案

关于万向节锁在Unity官方文档中有这样的描述:

欧拉角

在变换坐标中,Unity 使用矢量属性Transform.eulerAngles X、Y 和 Z 显示旋转。与法线矢量不同,这些值实际上表示绕 X、Y 和 Z 轴旋转的角度(以度为单位)。

欧拉角旋转围绕三个轴执行三个单独的旋转。Unity 依次围绕 z 轴、x 轴和 y 轴执行欧拉旋转。这种旋转方式就是外旋转;旋转发生时原始坐标系不会改变。

要旋转游戏对象,您可以在变换组件中输入您希望每个轴旋转多远的角度值。要使用脚本旋转游戏对象,请使用Transform.eulerAngles如果您转换为欧拉角来进行计算和旋转,则可能会出现万向节锁定问题。

万向节锁

当 3D 空间中的物体失去一定的自由度并且只能在二维空间内旋转时,称为万向节锁。如果两个轴平行,则欧拉角可能会发生万向节锁定。如果您不在脚本中将旋转值转换为欧拉角,则使用四元数应该可以防止万向节锁定。

如果您确实遇到万向节锁定问题,则在用于旋转时可以避免欧拉角Transform.RotateAround您还可以Quaternion.AngleAxis在每个轴上使用并将它们相乘(四元数乘法依次应用每个旋转)。

四元数

四元数为 3D 空间中空间方向和旋转的独特表示提供数学符号。四元数使用四个数字来编码 3D 中绕单位轴旋转的方向和角度。这四个值是复数而不是角度或度数。您可以研究四元数的数学以获取更多信息。

Unity 将旋转值转换为四元数来存储它们,因为四元数旋转计算高效且稳定。Unity 编辑器不会将旋转显示为四元数,因为单个四元数无法表示绕任何轴大于 360 度的旋转。

如果使用Quaternion类就可以直接使用四元数如果您使用脚本进行旋转,则可以使用四元数类和函数来创建和更改旋转值。您可以将值作为欧拉角应用于旋转,但需要将它们存储为四元数以避免出现问题。

具体的可以参考文档:Unity 中的旋转和方向(https://docs.unity3d.com/cn/current/Manual/QuaternionAndEulerRotationsInUnity.html)

 

所以尽量避免使用Transform.eulerAngles进行计算旋转,举个例子,鼠标控制相机的旋转你可能会这样写

1
2
3
4
5
6
7
8
void CameraRotate(float speed)
{
    Vector3 rot = transform.eulerAngles;
    rot.z = 0;
    rot.y -= Input.GetAxis("Mouse X") * speed * Time.deltaTime;
    rot.x += Input.GetAxis("Mouse Y") * speed * Time.deltaTime;
    transform.eulerAngles = rot;
}

  

放到Update每帧调用时,你观察Inspector面板会发现在x轴接近90度时,z轴居然不是0,出现这种现象也就是上面所说的万向节锁

那么该怎么避免呢,官方文档也给出了方案,定义一个全局的Vector3,在Start的时候,给Vector3赋值:

1
2
3
4
5
6
7
8
9
10
11
12
Vector3 currentEulerAngles;
void Start()
{
    currentEulerAngles = transform.eulerAngles;
}
void CameraRotate(float speed)
{
    currentEulerAngles.z = 0;
    currentEulerAngles.y -= Input.GetAxis("Mouse X") * speed * Time.deltaTime;
    currentEulerAngles.x += Input.GetAxis("Mouse Y") * speed * Time.deltaTime;
    transform.eulerAngles = currentEulerAngles;
}

  

这样通过累加currentEulerAngles就可以避免出现万向节锁,当然如果你想用Transform.Rotate之类的方法旋转也是可以的,

当时一定不要每帧都去获取transform.eulerAngles,而是定义一个全局的字段,去进行旋转计算赋值等操作

具体的文档可以参考:https://docs.unity3d.com/cn/current/ScriptReference/Transform-eulerAngles.html

https://docs.unity3d.com/cn/current/ScriptReference/Transform.Rotate.html

原创不易,如果觉得有用,留下你的足迹吧,你的鼓励我的动力

posted on   Jason_c  阅读(584)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示