当前位置: 首页 > java >正文

Unity基础-欧拉角和四元数

Unity基础-欧拉角和四元数

三、欧拉角和四元数

1. 为什么要使用四元数

Unity使用左手坐标系,X轴向右为正,Z轴向前为正,Y轴向上为正。
在Unity中,物体的旋转通常有两种表示方法:

欧拉角
  • 通过三个角度值(X, Y, Z)表示旋转
  • 优点:简单易懂,便于理解
  • 缺点:
    • 多个旋转顺序不同可能导致不同结果
    • 同一结果可能有不同种旋转角度
    • 存在万向节死锁(Gimbal Lock)问题

【补充说明】

  • 欧拉角的旋转顺序(如XYZ、ZYX等)会影响最终的旋转结果。Unity默认采用"ZXY"顺序。
  • 常见陷阱:多次叠加欧拉角旋转时,容易出现意外的旋转效果,建议尽量用四元数做插值和叠加。
四元数
  • 使用四个分量(x, y, z, w)表示旋转
  • 优点:
    • 可以避免万向节死锁问题
    • 计算效率高,旋转组合更稳定
  • 缺点:不够直观,难以理解

【补充说明】

  • 四元数的数学性质:
    • 单位四元数长度为1,表示纯旋转。
    • 四元数的共轭(Conjugate)可用于求逆旋转。
    • 四元数的逆(Inverse)常用于"从B到A的旋转"。

2. 什么是万向节死锁

当使用欧拉角进行旋转,第二个旋转轴(通常是Y)旋转到90度时,第一个旋转轴和第三个旋转轴会重合,导致失去一个维度的旋转轴,从而无法实现某些旋转效果。

3. 什么是四元数

轴-角对:在3D空间内,任意旋转都可以表示为绕一个轴旋转一个角度,这里的轴可以是任意方向(不局限于X、Y、Z)。

四元数的定义

对于给定旋转,假设为绕着n轴,旋转β度,n轴为(x, y, z),那么可以构成四元数:

  • 四元数Q = [cos(β/2), sin(β/2) * n]
  • 展开为:Q = [cos(β/2), sin(β/2)x, sin(β/2)y, sin(β/2)z]

在Unity中,rotation属性就是四元数类型。

// 在Unity中定义一个四元数
Quaternion q = new Quaternion(Mathf.Sin(30 * Mathf.Deg2Rad), 0, 0, Mathf.Cos(30 * Mathf.Deg2Rad));
// 利用轴角对定义一个四元数
// 注意:应为 Quaternion.AngleAxis 而不是 AngleAixs
Quaternion q = Quaternion.AngleAxis(60, Vector3.right);

4. 欧拉角和四元数的相互转化

// 欧拉角转化为四元数
Quaternion quaternion = Quaternion.Euler(0, 60, 0);
// 使用四元数旋转,完美解决了万向节死锁问题
this.transform.rotation *= quaternion;
// 四元数转化为欧拉角
Vector3 rot = (this.transform.rotation).eulerAngles;
rot += Vector3.up;
// 使用欧拉角旋转,存在万向节死锁问题
this.transform.rotation = Quaternion.Euler(rot);

5. 单位四元数

单位四元数表示没有旋转量(角位移)。
当角度为0或者360度时,对于给定轴都会得到单位四元数。
[1, (0,0,0)] 和 [-1, (0,0,0)] 都是单位四元数,表示没有旋转量。

// 使用单位四元数进行对象实例化
Instantiate(target, Vector3.zero, Quaternion.identity);

6. 四元数差值运算

四元数中同样提供如同Vector3中的差值运算Lerp和Slerp。

  • Lerp:线性插值,速度快,但大角度旋转时效果不如Slerp
  • Slerp:球形插值,旋转更自然,常用于动画、摄像机等平滑过渡
// 使用差值先快后慢过渡
a.transform.rotation = Quaternion.Slerp(a.transform.rotation, target.transform.rotation, Time.deltaTime);
// 使用差值匀速过渡
float time = 0;
time += Time.deltaTime;
b.transform.rotation = Quaternion.Slerp(startQua, target.transform.rotation, time);

【补充说明】

  • Slerp(球形插值)适合大角度、需要平滑过渡的旋转,动画和摄像机常用。
  • Lerp(线性插值)速度快,适合小角度、对精度要求不高的场景。
  • 实际开发中,推荐优先使用Slerp进行旋转插值。

7. LookRotation(朝向旋转)

Quaternion.LookRotation 可以将传入的面朝向量转换为对应的四元数角度信息。

应用示例:
当需要改变人物的面朝方向时,只需将目标面朝向向量传入该函数,即可得到目标四元数角度信息。随后,将人物的四元数角度信息更新为获得的结果,即可实现转向效果。

// 向量指向转四元数LookRotation
lookA.rotation = Quaternion.LookRotation(lookB.position - lookA.position);

关键点:

  • 输入:面朝向量(表示目标方向)
  • 输出:对应的四元数角度信息
  • 用途:快速实现物体或角色的方向调整

【补充说明】

  • LookRotation的输入向量不能为零向量,否则会报错。
  • 可以指定第二个参数(up方向),如Quaternion.LookRotation(forward, up),以控制物体的"头顶"朝向。

【补充:四元数在Unity常见应用场景】

  • 角色和摄像机的平滑旋转
  • 物体朝向目标(如导弹追踪、角色面向)
  • 动画骨骼插值
  • 3D物理模拟中的旋转
http://www.xdnf.cn/news/12661.html

相关文章:

  • 【Elasticsearch】映射:Join 类型、Flattened 类型、多表关联设计
  • 基于springboot的藏文古籍系统
  • Nature子刊:16S宏基因组+代谢组学联动,借助MicrobiomeGS2建模揭示IBD代谢治疗新靶点
  • Java高级 | 【实验六】Springboot文件上传和下载
  • Python 中的MVC与MVP 框架与示例
  • LVGL对显示接口的要求
  • 闲庭信步使用SV搭建图像测试平台:第一课——图片的读写
  • 【商城saas和商城源码的区别】
  • 【Zephyr 系列 13】BLE Mesh 入门实战:构建基础节点通信与中继组播系统
  • 类型别名与类型自动推导
  • Redis数据持久化之RDB快照
  • 【走好求职第一步】求职OMG——见面课测验4
  • SAP学习笔记 - 开发27 - 前端Fiori开发 Routing and Navigation(路由和导航)
  • 算术图片验证码(四则运算)+selenium
  • 【大模型】大模型RAG(Retrieval-Augmented Generation)面试题合集
  • 欢乐熊大话蓝牙知识16:蓝牙是怎么找设备的?扫描与广播的“对话内幕”
  • Shell编程精髓:表达式与数组实战指南
  • DbServer链接KingBase8(人大)数据库
  • Android座舱系统Agent改造方案
  • day 47
  • 微前端架构下的B端页面设计:模块化与跨团队协作的终极方案
  • Python爬虫-爬取各省份各年份高考分数线数据,进行数据分析
  • 国产pcie switch,支持PCIE 3.0/4.0/5.0,支持昇腾310/910 GPU,支持龙芯、海光、飞腾
  • 小白成长之路-Linux Shell脚本练习
  • 2025年- H77-Lc185--45.跳跃游戏II(贪心)--Java版
  • Xilinx IP 解析之 Block Memory Generator v8.4 ——01-手册重点解读(仅 Native R
  • 前端开发面试题总结-JavaScript篇(二)
  • .Net Framework 4/C# 泛型的使用、迭代器和分部类
  • 本地windows服务器部署私有云网盘Nextcloud并无公网IP实现外部访问
  • 多线程中的泛型应用深度解析:类型安全与并发编程的完美融合