Unity入门学习(四)3D数学(4)之四元数Quaternion

目录

一、什么是四元数

二、和欧拉角的关联以及为什么会出现四元数

三、四元数的基本组成

Unity中的表示:

四、四元数Quaternion这个类中具有的属性和方法

常用属性

核心方法

五、四元数之间的计算

1. 叉乘(组合旋转)

2. 点积(相似度)

六、总结

四元数 Quaternion 属性与方法总结

详细说明

1. 属性

2. 方法

3. 运算符与静态方法


一、什么是四元数

定义
        四元数(Quaternion)是一种数学工具,用于表示三维空间中的旋转。它由四个分量组成:一个实部(w)和三个虚部(x, y, z),数学表达式为:
                                        q=w+xi+yj+zk
其中 

                                i^{2} + j^{2} + k^{2} = ijk = -1

        你可以想象四元数是一个“方向标记”,而欧拉角是“分解成三个步骤的转动角度”。四元数通过一种紧凑的数学形式直接描述方向,避免了欧拉角的分步旋转可能导致的万向节死锁问题。

Unity中的应用        
        在Unity中,所有Transform组件的旋转底层均由四元数实现。虽然开发者通常通过欧拉角(如Inspector面板中的Rotation)调整物体朝向,但Unity会自动将其转换为四元数存储。

二、和欧拉角的关联以及为什么会出现四元数

欧拉角的局限性
        万向节死锁(Gimbal Lock):当绕某一轴旋转90度时,另外两个轴的旋转会重合,导致丢失一个自由度。就是说当你转到90度时,你想单独再沿着某一条轴进行旋转,发现怎么都不可以
例如:飞机俯仰90度后,偏航和滚转将绕同一轴旋转,无法独立控制。
插值不平滑:直接对欧拉角插值会导致旋转路径不自然(如抖动或突变)。

四元数的优势
无万向节死锁:四元数通过四维空间描述旋转,避免了三维欧拉角的轴顺序问题。
平滑插值:支持球面线性插值(Slerp),保证旋转路径的最短性和平滑性。
计算高效:旋转合成和逆运算更高效,适合实时计算。

关联
转换关系:欧拉角可通过Quaternion.Euler()转换为四元数,反之通过Quaternion.eulerAngles属性获取。
 

三、四元数的基本组成

四元数构成
一个四元数包含一个标量和一个3D向量
[w,v],w为标量,v为3D向量
[w,(x,y,z)]
对于给定的任意的一个四元数:
表示3D空间中的一个旋转量

轴-角对
在3D空间中 任意旋转都可以表示 绕着某个轴旋转一个旋转角得到

注意:该轴并不是空间中的xyz中轴 而是任意一个轴
对于给定旋转 假设为绕着n轴 旋转β角度 n轴为(x,y,z)
那么可以构成的四元数为:
四元数Q = [cos(β/2),sin(β/2)n]
四元数Q = [cos(β/2,sin(β/2)x,sin(β/2)y,sin(β/2)z]

四元数Q则表示绕着轴n,旋转β度的旋转量

单位四元数
单位四元数表示没有旋转量(角位移)
当角度为0或者360度时
对于给定的轴都会得到单位四元数

[1,(0,0,0)]和[-1,(0,0,0)]都是单位四元数
表示没有旋转量

Unity中的表示:

Quaternion q = new Quaternion(x, y, z, w);
// 注意:Unity的构造函数参数顺序为(x, y, z, w)

例如:绕Y轴旋转90度的四元数:

Quaternion rotation = Quaternion.Euler(0, 90, 0);
// 等效于手动计算:
float angle = 90 * Mathf.Deg2Rad;
Quaternion q = new Quaternion(0, Mathf.Sin(angle/2), 0, Mathf.Cos(angle/2));

四、四元数Quaternion这个类中具有的属性和方法

常用属性
属性说明
identity单位四元数(无旋转)。
eulerAngles转换为欧拉角(只读)。
核心方法
方法说明示例
AngleAxis创建绕指定轴旋转角度的四元数。Quaternion.AngleAxis(90, Vector3.up)
Euler将欧拉角转换为四元数。Quaternion.Euler(0, 90, 0)
Slerp球面线性插值(平滑旋转)。Quaternion.Slerp(a, b, t)
Lerp线性插值(速度更快,但路径非最短)。Quaternion.Lerp(a, b, t)
Inverse返回反向旋转的四元数。Quaternion.Inverse(rotation)
LookRotation生成朝向某个方向的旋转。Quaternion.LookRotation(direction)

详细解释:

属性:

(1)identity:单位四元数(无旋转)
表示“不旋转”的状态,常用于初始化旋转或重置物体方向。

using UnityEngine;public class QuaternionExample : MonoBehaviour
{void Start(){// 将物体旋转重置为初始状态(无旋转)transform.rotation = Quaternion.identity;}
}


(2)eulerAngles:将四元数转换为欧拉角
返回当前四元数对应的欧拉角(只读属性),常用于调试或显示直观角度。

using UnityEngine;public class QuaternionExample : MonoBehaviour
{void Update(){// 实时输出物体的欧拉角Debug.Log("当前欧拉角:" + transform.rotation.eulerAngles);// 注意:直接修改 eulerAngles 可能导致问题,应通过 Quaternion.Euler() 设置// transform.eulerAngles = new Vector3(0, 90, 0); // 不推荐}
}

方法:

(1) AngleAxis:绕指定轴旋转指定角度
创建绕某个轴旋转一定角度的四元数,常用于自由轴旋转。

using UnityEngine;public class QuaternionExample : MonoBehaviour
{public float rotateSpeed = 90f; // 每秒旋转90度void Update(){// 绕Y轴旋转(按每秒 rotateSpeed 度旋转)float angle = rotateSpeed * Time.deltaTime;Quaternion rotation = Quaternion.AngleAxis(angle, Vector3.up);transform.rotation = rotation * transform.rotation;}
}

(2) Euler:欧拉角转四元数
将欧拉角转换为四元数,避免直接操作 eulerAngles 导致的问题。

using UnityEngine;public class QuaternionExample : MonoBehaviour
{void Start(){// 设置物体绕Y轴旋转90度Quaternion targetRotation = Quaternion.Euler(0, 90, 0);transform.rotation = targetRotation;}
}

(3) Slerp:球面线性插值
沿球面最短路径平滑插值,适合摄像机跟踪或自然旋转。

using UnityEngine;public class QuaternionExample : MonoBehaviour
{public Transform target; // 拖入目标物体public float speed = 0.5f;void Update(){// 计算目标方向Vector3 direction = target.position - transform.position;Quaternion targetRotation = Quaternion.LookRotation(direction);// 使用Slerp平滑旋转transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, speed * Time.deltaTime);}
}
//先快后慢
//A.rotation = Quaternion.Slerp(A.rotation,target.rotation,Time.deltaTime);//匀速变化
//time += Time.deltaTime;
//B.rotation = Quaternion.Slerp(start,target.rotation,time);

效果:物体会平滑转向目标物体,路径无抖动。 

(4) Lerp:线性插值
快速插值但路径非最短,适合对平滑性要求不高的场景。

using UnityEngine;public class QuaternionExample : MonoBehaviour
{public Transform target;public float speed = 1f;void Update(){Quaternion targetRotation = Quaternion.LookRotation(target.position - transform.position);transform.rotation = Quaternion.Lerp(transform.rotation, targetRotation, speed * Time.deltaTime);}
}

(5) Inverse:反向旋转
获取当前旋转的逆旋转,常用于坐标系转换或相对旋转。

using UnityEngine;public class QuaternionExample : MonoBehaviour
{public Transform otherObject;void Update(){// 计算当前旋转的逆旋转Quaternion inverseRotation = Quaternion.Inverse(transform.rotation);// 将另一个物体的旋转设置为当前物体的逆旋转otherObject.rotation = inverseRotation;}
}

效果otherObject 会始终与当前物体保持反向旋转。 

(6) LookRotation:朝向某个方向
使物体正面朝向指定方向,常用于控制角色或摄像机。

using UnityEngine;public class QuaternionExample : MonoBehaviour
{public Vector3 targetDirection = Vector3.forward; // 默认朝前void Update(){// 动态让物体朝向 targetDirection 方向Quaternion targetRotation = Quaternion.LookRotation(targetDirection);transform.rotation = targetRotation;}
}

效果:物体正面始终指向 targetDirection(可修改为鼠标或目标位置)。 

完整臻享版:

using UnityEngine;public class QuaternionDemo : MonoBehaviour
{public Transform target;public float rotateSpeed = 90f;public float slerpSpeed = 0.5f;void Start(){// 初始化无旋转transform.rotation = Quaternion.identity;}void Update(){// 1. AngleAxis 持续绕Y轴旋转float angle = rotateSpeed * Time.deltaTime;Quaternion rotation = Quaternion.AngleAxis(angle, Vector3.up);transform.rotation = rotation * transform.rotation;// 2. LookRotation 朝向目标if (target != null){Vector3 direction = target.position - transform.position;Quaternion targetRot = Quaternion.LookRotation(direction);transform.rotation = Quaternion.Slerp(transform.rotation, targetRot, slerpSpeed * Time.deltaTime);}// 3. 输出当前欧拉角Debug.Log("当前欧拉角:" + transform.rotation.eulerAngles);}
}

五、四元数之间的计算

1. 叉乘(组合旋转)

四元数乘法表示旋转的叠加,顺序为从右到左应用。
公式

                        q_{result} = q_{1} \times q_{2}

注意啊不满足交换律:即:

                ​​​​​​​        q_{1} \times q_{2} \neq q_{2} \times q_{1}

Quaternion qY = Quaternion.Euler(0, 90, 0); // 绕Y轴转90度
Quaternion qX = Quaternion.Euler(90, 0, 0); // 绕X轴转90度// 顺序1:先绕Y轴转,再绕X轴转
transform.rotation = qX * qY;// 顺序2:先绕X轴转,再绕Y轴转
transform.rotation = qY * qX;
/*效果:顺序1:物体会先面向右侧(Y轴旋转),然后向上翻转(X轴旋转)。顺序2:物体会先向上翻转(X轴旋转),然后面向右侧(Y轴旋转)。
最终朝向完全不同(可通过运行代码观察)。
*/
2. 点积(相似度)

四元数的点乘(Quaternion.Dot(q1, q2))返回值的范围是 [-1, 1],表示两个旋转的相似程度:

1:完全相同旋转。
-1:互为反向旋转。
0:旋转方向正交(无关)。

         Dot(q_{1},q_{2}) = q_{1}.x \cdot q_{2}.x +q_{1}.y \cdot q_{2}.y +q_{1}.z \cdot q_{2}.z +q_{1}.w \cdot q_{2}.w                         

 实际应用场景
(1) 判断旋转是否完成

Quaternion targetRotation = Quaternion.Euler(0, 90, 0);
float similarity = Quaternion.Dot(transform.rotation, targetRotation);if (similarity > 0.999f) {Debug.Log("旋转完成!");
}

(2) 平滑过渡检测 在插值旋转时,若相似度接近1,可提前终止插值以优化性能:

Quaternion current = transform.rotation;
Quaternion target = Quaternion.Euler(0, 90, 0);
float t = Quaternion.Dot(current, target);if (t < 0.99f) {transform.rotation = Quaternion.Slerp(current, target, Time.deltaTime * speed);
}

(3) 反向旋转检测

Quaternion inverse = Quaternion.Inverse(currentRotation);
float similarity = Quaternion.Dot(currentRotation, inverse);if (similarity < -0.999f) {Debug.Log("当前旋转与反向旋转对齐");
}
操作数学本质Unity中的作用典型场景
乘法(×)旋转叠加(顺序敏感)组合多个旋转,或转换坐标系角色转身+抬头、动画叠加
点乘(Dot)四维空间中的夹角余弦检测旋转相似度、判断旋转完成或反向插值优化、AI朝向检测、反向动作触发

综合对比:

using UnityEngine;public class QuaternionOperationsDemo : MonoBehaviour
{void Start(){// 1. 验证乘法顺序Quaternion qY = Quaternion.Euler(0, 90, 0);Quaternion qX = Quaternion.Euler(90, 0, 0);Debug.Log("顺序1 (qX*qY): " + (qX * qY).eulerAngles); // 输出 (90, 90, 0)Debug.Log("顺序2 (qY*qX): " + (qY * qX).eulerAngles); // 输出 (90, 90, 270)// 2. 验证点乘相似度Quaternion a = Quaternion.identity;Quaternion b = Quaternion.Euler(0, 90, 0);Quaternion c = Quaternion.Inverse(b);Debug.Log("a vs b: " + Quaternion.Dot(a, b)); // 约0.7(不相似)Debug.Log("b vs b: " + Quaternion.Dot(b, b)); // 1(完全一致)Debug.Log("b vs c: " + Quaternion.Dot(b, c)); // -1(完全反向)}
}

3. 逆运算

四元数的逆(Inverse)表示反向旋转。

公式

        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        q^{-1} = (-\frac{x}{||q||},-\frac{y}{||q||},-\frac{z}{||q||},-\frac{w}{||q||},)

例如:

Quaternion inverse = Quaternion.Inverse(rotation);

        ​​​​​​​       这里同上,不再赘述

六、总结

四元数 Quaternion 属性与方法总结

属性/方法参数返回值简单示例
identityQuaterniontransform.rotation = Quaternion.identity;
eulerAnglesVector3(欧拉角)Vector3 angles = transform.rotation.eulerAngles;
AngleAxisfloat angleVector3 axisQuaternionQuaternion q = Quaternion.AngleAxis(90, Vector3.up);
Eulerfloat xfloat yfloat z 或 Vector3 eulerQuaternionQuaternion q = Quaternion.Euler(0, 90, 0);
SlerpQuaternion aQuaternion bfloat tQuaternionQuaternion.Slerp(current, target, Time.deltaTime * speed);
LerpQuaternion aQuaternion bfloat tQuaternionQuaternion.Lerp(current, target, Time.deltaTime * speed);
InverseQuaternion rotationQuaternionQuaternion inverse = Quaternion.Inverse(transform.rotation);
LookRotationVector3 forwardVector3 upwards=Vector3.up(可选)QuaternionQuaternion q = Quaternion.LookRotation(target.position - transform.position);
operator *Quaternion aQuaternion b(或 Vector3 向量)Quaternion 或 Vector3Quaternion combined = q1 * q2;
Vector3 rotated = q * Vector3.forward;
DotQuaternion aQuaternion bfloat(相似度)float similarity = Quaternion.Dot(q1, q2);

详细说明

1. 属性
属性说明
identity表示无旋转的四元数,等同于 new Quaternion(0, 0, 0, 1)
eulerAngles将四元数转换为欧拉角(单位为度),仅用于调试,不可直接修改。
2. 方法
方法说明
AngleAxis绕指定轴旋转指定角度(单位为度)。
Euler将欧拉角转换为四元数(单位为度)。
Slerp沿球面最短路径插值,适合平滑旋转(如摄像机跟随)。
Lerp线性插值,速度更快但路径可能非最短。
Inverse返回反向旋转的四元数(等效于逆矩阵)。
LookRotation生成朝向指定方向的四元数,默认以 Vector3.up 为向上方向。
3. 运算符与静态方法
操作说明
operator *组合两个四元数的旋转,或对向量应用旋转(顺序为从右到左)。
Dot计算两个四元数的四维点积,用于判断旋转相似度(1为相同,-1为反向)。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/906376.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

活体检测接口全面评测:2025年活体检测选择指南

一、活体检测&#xff1a;数字化时代的身份验证基石 活体检测是一种通过分析人体生物特征动态变化来验证身份真实性的技术&#xff0c;其核心在于区分真实人体与伪造样本&#xff08;如照片、视频、3D 面具等&#xff09;。技术原理主要基于以下维度&#xff1a; 多模态数据采…

物联网工程毕业设计课题实践指南

1. 智能家居控制系统 1.1 基于ZigBee的智能家居控制 实践过程 硬件选型主控:CC2530/CC2531传感器:温湿度、光照、人体红外执行器:继电器、电机、LED灯系统架构 A[传感器层] --> B[ZigBee网络] B --> C[网关] C --> D[云平台] D --> E[手机APP] 开…

电网中窃电分析:概念、算法与应用

一、引言 在现代电力系统中&#xff0c;窃电行为是一个严重影响电网经济运行和供电秩序的问题。窃电不仅导致供电企业的经济损失&#xff0c;破坏了电力市场的公平性&#xff0c;还可能对电网的安全稳定运行构成威胁&#xff0c;甚至引发安全事故。随着科技的不断进步&#xff…

一洽小程序接入说明

接入说明 文档以微信小程序作为示例介绍&#xff0c;其他小程序接入操作与此类似 1、添加校验文件 开发者使用微信小程序提供的 webview 组件可以实现打开一洽的H5对话 小程序的“域名配置”中添加一洽的对话域名地址&#xff0c;需要获取校验文件提供给一洽放在域名根目录下…

【数据结构 -- AVL树】用golang实现AVL树

目录 引言定义旋转方式LL型RR型LR型RL型 实现结构获取结点高度平衡因子更新高度左旋右旋插入结点中序遍历 引言 AVL树&#xff0c;基于二叉搜索树通过平衡得到 前面我们知道&#xff0c;通过&#x1f517;二叉搜索树可以便捷快速地查找到数据&#xff0c;但是当序列有序时&am…

PyTorch图像识别模型和图像分割模型体验

文章目录 仓库地址练习&#xff1a;图像自动识别模型数据集说明模型训练和保存导入数据集搭建神经网络训练和保存实现 模型测试测试代码测试结果 练习&#xff1a;图像自动分割模型模型训练和保存加载数据集搭建神经网络训练和保存 模型测试测试代码测试效果 仓库地址 图像识别…

威纶通触摸屏IP地址设定步骤及程序下载指南

在使用威纶通触摸屏时&#xff0c;正确设定IP地址以及完成程序下载是确保其正常运行和实现功能的关键步骤。本文将详细介绍威纶通触摸屏IP地址设定步骤及程序下载的方法。 一、IP地址设定步骤 &#xff08;一&#xff09;前期准备 确保威纶通触摸屏已经通电并启动&#xff0…

一文读懂|大模型智能体互操作协议:MCP/ACP/A2A/ANP

导读 随着推理大模型的出现&#xff08;deepseek&#xff0c;Qwen3等&#xff09;&#xff0c;进一步地推进了大模型的智能体系统发展。然而&#xff0c;如何使智能体更好的调用外部工具&#xff0c;智能体与智能体之间如何有机地协作&#xff0c;仍然没有一个完美的答案。这篇…

前端下载ZIP包方法总结

在前端实现下载 ZIP 包到本地&#xff0c;通常有以下几种方法&#xff0c;具体取决于 ZIP 包的来源&#xff08;静态文件、后端生成、前端动态生成等&#xff09;&#xff1a; 方法 1&#xff1a;直接下载静态文件&#xff08;最简单&#xff09; 如果 ZIP 包是服务器上的静态…

简单使用Slidev和PPTist

简单使用Slidev和PPTist 1 简介 前端PPT制作有很多优秀的工具包&#xff0c;例如&#xff1a;Slidev、revealjs、PPTist等&#xff0c;Slidev对Markdown格式支持较好&#xff0c;适合与大模型结合使用&#xff0c;选哟二次封装&#xff1b;revealjs适合做数据切换&#xff0c…

数据挖掘:从数据堆里“淘金”,你的数据价值被挖掘了吗?

数据挖掘&#xff1a;从数据堆里“淘金”&#xff0c;你的数据价值被挖掘了吗&#xff1f; 在这个数据爆炸的时代&#xff0c;我们每天都在产生海量信息&#xff1a;社交媒体上的点赞、网购时的浏览记录&#xff0c;甚至是健身手环记录下的步数。这些数据本身可能看似杂乱无章…

程序运行报错分析文档

zryhuawei:~/src/modules/Connect$ ./newbuild/OpConnectAidTool \WARNING: MYSQL_OPT_RECONNECT is deprecated and will be removed in a future version. replace into process_tracking (step_id,date,status,context_data,start_time,end_time,error_log) values(?,?,?…

基于flask+vue的电影可视化与智能推荐系统

基于flaskvue爬虫的电影数据的智能推荐与可视化系统&#xff0c;能展示电影评分、评论情感分析等直观的数据可视化图表&#xff0c;还能通过协同过滤算法为用户提供个性化电影推荐&#xff0c;帮助用户发现更多感兴趣的电影作品&#xff0c;具体界面如图所示。 本系统主要技术架…

BYUCTF 2025

几周没会的比赛了&#xff0c;都是一题游。这周的BYU还不错&#xff0c;难度适中&#xff0c;只是时间有点短。周末时间不够。 Crypto Many Primes from Crypto.Util.number import bytes_to_long, getPrime import randomflag open("flag.txt").read().encode()…

链表的面试题8之环形链表

许久不见&#xff0c;那么这是最后倒数第三题了&#xff0c;这道题我们来看一下环形链表。 老规矩贴链接&#xff1a;141. 环形链表 - 力扣&#xff08;LeetCode&#xff09; 目录 倒数第k个元素 获取中间元素的问题。 双指针 来&#xff0c;大致看一下题目&#xff0c;这…

在 JavaScript 中正确使用 Elasticsearch,第二部分

作者&#xff1a;来自 Elastic Jeffrey Rengifo 回顾生产环境中的最佳实践&#xff0c;并讲解如何在无服务器环境中运行 Elasticsearch Node.js 客户端。 想获得 Elastic 认证&#xff1f;查看下一期 Elasticsearch Engineer 培训的时间&#xff01; Elasticsearch 拥有大量新…

2025年网站安全防御全解析:应对DDoS与CC攻击的智能策略

2025年&#xff0c;随着AI技术与物联网设备的深度融合&#xff0c;DDoS与CC攻击的规模与复杂度持续升级。攻击者不仅利用T级流量洪泛冲击带宽&#xff0c;还通过生成式AI伪造用户行为&#xff0c;绕过传统防御规则。如何在保障业务高可用的同时抵御混合型攻击&#xff1f;本文将…

window 安装 wsl + cuda + Docker

WSL 部分参考这里安装&#xff1a; Windows安装WSL2 Ubuntu环境 - 知乎 如果出现错误&#xff1a; WslRegisterDistribution failed with error: 0x800701bc 需要运行&#xff1a;https://crayon-shin-chan.blog.csdn.net/article/details/122994190 wsl --update wsl --shu…

《MambaLLIE:基于隐式Retinex感知的低光照增强框架与全局-局部状态空间建模》学习笔记

Paper:2405.16105 Github:GitHub - wengjiangwei/MambaLLIE 目录 摘要 一、介绍 二、相关工作 2.1 低光图像增强 2.2 视觉空间状态模型 三、方法 3.1 预备知识 3.2 整体流程 3.3 全局优先-局部次之状态空间块 四、实验 4.1 基准数据集与实施细节 4.2 对比实验 4…

微信小程序:封装request请求、解决请求路径问题

一、创建文件 1、创建请求文件 创建工具类文件request.js,目的是用于发送请求 二、js接口封装 1、写入接口路径 创建一个变量BASE_URL专门存储api请求地址 2、获取全局的token变量 从缓存中取出token的数据 3、执行请求 (1)方法中接收传递的参数 function request(url,…