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为反向)。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FAREWELL00075

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值