2025Unity中的核心数学工具(三)四元数(穿插Unity实战相关案例)

一、为何使用四元数

1.欧拉角

定义:由三个角度(x,y,z)组成 在特定坐标系下用于描述物体的旋转量

注意:空间中的任意旋转都可以分解成绕 三个互相垂直轴的三个旋转角组成的序列

2.欧拉角旋转约定

**heading-pitch-bank:**是一种最常用的旋转序列约定 (Y-X-Z约定)

heading:物体绕自身的对象坐标系的Y轴,旋转的角度

pitch:物体绕自身的对象坐标系的X轴,旋转的角度

bank:物体绕自身的对象坐标系的Z轴,旋转的角度

3.Unity中的欧拉角

Inspector窗口中调节的Rotation就是欧拉角

this.transform.eulerAngles得到的就是欧拉角角度

4.欧拉角的优缺点

(1)优点

直观、易理解

存储空间小(三个数表示)

可以进行从一个方向到另一个方向旋转大于180度的角度

(2)缺点

同一旋转的表示不唯一

万向节死锁

**5.**万向节死锁

当某个特定轴达到某个特殊值时 ,绕一个轴旋转可能会覆盖住另一个轴的旋转,从而失去一维自由度

例如:Unity中X轴达到90度时 会产生万向节死锁

Tips:四元数旋转不存在万向节死锁问题


二、四元数是什么

四元数是什么

1.四元数构成

(1)概念

四元数是简单的超复数, 由实数加上三个虚数单位组成 ,主要用于在三维空间中表示旋转

(2)构成

(3)轴-角对

含义:在3D空间中,任意旋转都可以表示 ,绕着某个轴旋转一个旋转角得到。
注意:该轴并不是空间中的x,y,z轴 ,而是任意一个轴
对于给定旋转,假设为绕着n轴,旋转β度,n轴为(x,y,z) ,那么可以构成四元数为:


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

2.Unity中的四元数

Quaternion 是Unity中表示四元数的结构体

(1)Unity中的四元数初始化方法

cs 复制代码
 #region 知识点一 四元数 Quaternion
 //四元数Q = [cos(β/2),  sin(β/2)x, sin(β/2)y, sin(β/2)z]
 //计算原理
 //Quaternion q = new Quaternion(Mathf.Sin(30 * Mathf.Deg2Rad), 0, 0, Mathf.Cos(30 * Mathf.Deg2Rad));
 //提供的轴角对 初始化 四元数的方法
 Quaternion q = Quaternion.AngleAxis(60, Vector3.right);

 //创建一个立方体
 GameObject obj = GameObject.CreatePrimitive(PrimitiveType.Cube);
 obj.transform.rotation = q;

 #endregion

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

欧拉角转四元数


四元数转欧拉角

cs 复制代码
 #region 知识点二 四元数和欧拉角转换
 //1.欧拉角转四元数
 Quaternion q2 = Quaternion.Euler(60, 0, 0);
 GameObject obj2 = GameObject.CreatePrimitive(PrimitiveType.Cube);
 obj2.transform.rotation = q2;
 //2.四元数转欧拉角
 print(q2.eulerAngles);
 #endregion

4.四元数弥补的欧拉角缺点


三、四元数

1.单位四元数

(1)含义

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

cs 复制代码
 #region 知识点一 单位四元数
 print(Quaternion.identity);
 //testObj.rotation = Quaternion.identity;

 Instantiate(testObj, Vector3.zero, Quaternion.identity);
 #endregion

2.插值运算

cs 复制代码
 //无限接近 先快后慢
 A.transform.rotation = Quaternion.Slerp(A.transform.rotation, target.rotation, Time.deltaTime);

 //匀速变化 time>=1到达目标
 time += Time.deltaTime;
 B.transform.rotation = Quaternion.Slerp(start, target.rotation, time);

3.向量方向 转换为 对应四元数角度

Quaternino.LookRotation(面朝向量);
LookRoataion方法可以将传入的面朝向量
转换为对应的四元数角度信息

cs 复制代码
#region  LookRotation
//Quaternion q = Quaternion.LookRotation(lookB.position - lookA.position);
//lookA.rotation = q;
lookA.MyLookAt(lookB);
#endregion

四、四元数练习题

1.题目

(1)利用四元数的LookRotation方法,实现LookAt的效果
(2)将之前摄像机移动的练习题中的LookAt换成LookRotation实现
并且通过Slerp来缓慢看向玩家

2.实现

cs 复制代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public static class Tools
{
    public static void MyLookAt(this Transform obj, Transform target)
    {
        Vector3 vec = target.position - obj.position;
        obj.transform.rotation = Quaternion.LookRotation(vec);
    }
}
cs 复制代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CameraMove : MonoBehaviour
{
    public float zOffect = 4;
    public float yOffect = 7;
    public Transform target;

    private Vector3 targetPos;
    public float moveSpeed;
    private Vector3 startPos;
    private float time;

    private Quaternion targetQ;
    public float roundSpeed;
    private float roundTime;
    private Quaternion startQ;

    // Start is called before the first frame update
    void Start()
    {
        
    }

    
    void LateUpdate()
    {
        //先快后慢的移动
        //if(targetPos != target.position + -target.forward * zOffect + target.up * yOffect)
        //{
        //    targetPos = target.position + -target.forward * zOffect + target.up * yOffect;
        //}
        ////摄像机的位置 等于目标的位置 进行向量偏移
        ////先朝目标对象的 面朝向的反方向平移4米 再朝目标的头顶位置 平移7米
        //this.transform.position = Vector3.Lerp(this.transform.position, targetPos, Time.deltaTime*moveSpeed);

        //匀速移动
        if (targetPos != target.position + -target.forward * zOffect + target.up * yOffect)
        {
            targetPos = target.position + -target.forward * zOffect + target.up * yOffect;
            startPos = this.transform.position;
            time = 0;
        }
        time += Time.deltaTime;
        this.transform.position = Vector3.Lerp(startPos, targetPos, time* moveSpeed);

        //用目标的位置 减去 摄像机的位置 得到新的面朝向向量
        //targetQ = Quaternion.LookRotation(target.position - this.transform.position);
        //先快后慢
        //this.transform.rotation = Quaternion.Slerp(this.transform.rotation, targetQ, Time.deltaTime* roundSpeed);
        //匀速旋转
        if( targetQ != Quaternion.LookRotation(target.position - this.transform.position))
        {
            targetQ = Quaternion.LookRotation(target.position - this.transform.position);
            roundTime = 0;
            startQ = this.transform.rotation;
        }
        roundTime += Time.deltaTime;
        this.transform.rotation = Quaternion.Slerp(startQ, targetQ, roundTime * roundSpeed);
        //this.transform.LookAt(target);
    }
}

五、四元数计算

1.四元数相乘

2.四元数相乘向量

3.总结


六、四元数习题案例

1.题目

模拟飞机发射不同类型子弹的方法 单发,双发,扇形,环形

2.实现

效果演示

子弹轨迹

代码实现

cs 复制代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public enum E_FireType
{
    //单发
    One,
    //双发
    Two,
    //扇形
    Three,
    //环形
    Round
}
public class shoot : MonoBehaviour
{
    private E_FireType nowType = E_FireType.One;

    public GameObject bullet;

    public int roundNum = 4;

    // Start is called before the first frame update
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Alpha1))
        {
            nowType = E_FireType.One;
        }
        else if (Input.GetKeyDown(KeyCode.Alpha2))
        {
            nowType = E_FireType.Two;
        }
        else if (Input.GetKeyDown(KeyCode.Alpha3))
        {
            nowType = E_FireType.Three;
        }
        else if (Input.GetKeyDown(KeyCode.Alpha4))
        {
            nowType = E_FireType.Round;
        }

        if (Input.GetKeyDown(KeyCode.Space))
        {
            Fire();
        }
    }

    private void Fire()
    {
        switch (nowType)
        {
            case E_FireType.One:
                Instantiate(bullet, this.transform.position, this.transform.rotation);
                break;
            case E_FireType.Two:
                Instantiate(bullet, this.transform.position - this.transform.right * 0.5f, this.transform.rotation);
                Instantiate(bullet, this.transform.position + this.transform.right * 0.5f, this.transform.rotation);
                break;
            case E_FireType.Three:
                //朝自己的面朝向发射
                Instantiate(bullet, this.transform.position, this.transform.rotation);
                //朝自己左侧旋转20度再发射------知识点 四元数*四元数=一个新的四元数 相当于是旋转量的叠加
                Instantiate(bullet, this.transform.position, this.transform.rotation * Quaternion.AngleAxis(-20, Vector3.up));
                //朝自己左侧旋转20度再发射------知识点 四元数*四元数=一个新的四元数 相当于是旋转量的叠加
                Instantiate(bullet, this.transform.position, this.transform.rotation * Quaternion.AngleAxis(20, Vector3.up));
                break;
            case E_FireType.Round:
                float angle = 360 / roundNum;
                for (int i = 0; i < roundNum; i++)
                    Instantiate(bullet, this.transform.position, this.transform.rotation * Quaternion.AngleAxis(i * angle, Vector3.up));
                break;
        }
    }

}
cs 复制代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class bullet : MonoBehaviour
{
    public float moveSpeed = 10;
    void Start()
    {
        Destroy(this.gameObject, 5);
    }

    void Update()
    {
        this.transform.Translate(Vector3.forward * moveSpeed * Time.deltaTime);
    }
}
相关推荐
python_use4 小时前
SDL+WebGpu跨平台加速学习笔记
游戏引擎
千忧散5 小时前
Unity Socket学习笔记 (三)TCP&UDP
笔记·学习·unity·c#
君莫愁。8 小时前
【Unity】构建超实用的有限状态机管理类
unity·c#·游戏引擎·有限状态机
AA陈超10 小时前
虚幻引擎5 GAS开发俯视角RPG游戏 P05-01.创建游戏玩法标签
c++·游戏·ue5·游戏引擎·虚幻
EQ-雪梨蛋花汤12 小时前
【Unity笔记】Unity Lighting Settings 全解析:一文读懂烘焙光照的每个参数(VR项目Lighting优化)
笔记·unity·vr
爱吃小胖橘1 天前
Unity网络开发--超文本传输协议Http(1)
开发语言·网络·网络协议·http·c#·游戏引擎
BrightMZM1 天前
记录一下Unity的BUG,Trial Version
unity·bug·打包·trial
▍ 小太阳 ☼1 天前
Unity2022Navigation系统打开方式
unity·游戏引擎
qq_170264752 天前
unity升级对ab变更的影响
unity·游戏引擎