3D数学基础-欧拉角和四元数

本文深入探讨了Unity中欧拉角和四元数的运用,包括它们的优点、缺点及常见API。通过具体代码示例,讲解了如何使用欧拉角和四元数进行物体旋转,以及如何利用向量和四元数计算物体右前方特定位置的坐标。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

欧拉角

在这里插入图片描述

优点

在这里插入图片描述

缺点

在这里插入图片描述

万向节死锁

在这里插入图片描述

EulerDemo.cs

using UnityEngine;
using System.Collections;

/// <summary>
/// 
/// </summary>
public class EulerDemo : MonoBehaviour
{
    public Vector3 euler;
    private void OnGUI()
    {
        euler = transform.eulerAngles;

        if (GUILayout.RepeatButton("沿X轴旋转"))
        {
            //Vector3 euler = transform.eulerAngles;
            //欧拉角 没有 方向 和 大小的概念。
            //x  y   z  沿某个轴的旋转角度 
            transform.eulerAngles += new Vector3(1, 0, 0);
        }
        if (GUILayout.RepeatButton("沿Y轴旋转"))
        {
            transform.eulerAngles += Vector3.up;
        }
        if (GUILayout.RepeatButton("沿Z轴旋转"))
        {
            transform.eulerAngles += Vector3.forward;
        }
    }
 
}

四元数

在这里插入图片描述

基本运算

在这里插入图片描述
在这里插入图片描述

优点

在这里插入图片描述

缺点

在这里插入图片描述

常用API

在这里插入图片描述

QuaternionDemo.cs

using UnityEngine;
using System.Collections;

/// <summary>
/// 
/// </summary>
public class QuaternionDemo : MonoBehaviour
{
    private void Start()
    {
        //物体沿Y轴旋转50度
        Vector3 axis = Vector3.up;
        float rad = 50 * Mathf.Deg2Rad;
        Quaternion qt = new Quaternion();
        qt.x = Mathf.Sin(rad / 2) * axis.x;
        qt.y = Mathf.Sin(rad / 2) * axis.y;
        qt.z = Mathf.Sin(rad / 2) * axis.z;
        qt.w = Mathf.Cos(rad / 2);

        //transform.rotation = qt;
        transform.rotation = Quaternion.Euler(0, 50, 0);

        Debug.Log(transform.eulerAngles);
    }

    //计算
    private void OnGUI()
    { 
        if (GUILayout.RepeatButton("沿X轴旋转"))
        {  
            transform.rotation *= Quaternion.Euler(1, 0, 0);
            //transform.Rotate(1, 0, 0); //Rotate通过四元数实现
        }
        if (GUILayout.RepeatButton("沿Y轴旋转"))
        {
            transform.rotation *= Quaternion.Euler(0, 1, 0);
        }
        if (GUILayout.RepeatButton("沿Z轴旋转"))
        {
            transform.rotation *= Quaternion.Euler(0, 0, 1);
        }
    }

    private void Update()
    {
        Demo01();
    }

}

QuaternionAPI.cs

using UnityEngine;
using System.Collections;

/// <summary>
/// 
/// </summary>
public class QuaternionAPI : MonoBehaviour
{
    private void Start()
    {  
        Quaternion qt = transform.rotation;
        //1. 四元数  -->  欧拉角
        Vector3 euler = qt.eulerAngles;
        //2.欧拉角 --> 四元数
        Quaternion qt02 = Quaternion.Euler(0, 90, 0);
        //3.轴 / 角 旋转
        //transform.rotation = Quaternion.AngleAxis(30, Vector3.up);
        //transform.localRotation = Quaternion.AngleAxis(30, Vector3.up);  
    }

    public Transform target;
    private void Update()
    {
        //4. 注视旋转
        //Quaternion dir = Quaternion.LookRotation(target.position - transform.position);
        //transform.rotation = dir;
        //transform.LookAt(target.position);

        //5.Lerp 差值旋转  由快到慢
        //transform.rotation = Quaternion.Lerp(transform.rotation, dir, 0.1f);

        //6.RotateTowards    匀速旋转
        //transform.rotation = Quaternion.RotateTowards(transform.rotation, dir, 0.1f);
         
        //Quaternion dir = Quaternion.Euler(0, 180, 0);
        //transform.rotation = Quaternion.Lerp(transform.rotation, dir, 0.005f);
        ////7. 四元数计算角度差
        //if (Quaternion.Angle(transform.rotation, dir) < 30)
        //    transform.rotation = dir;

        //8. 从?到?的旋转
        transform.rotation = Quaternion.FromToRotation(Vector3.right, target.position - transform.position);
      
    }
 
}

练习一:计算物体右前方30度10m处坐标

向量法

 //练习
    private void Demo07()
    { 
        //计算:前右方30度  10米处世界坐标 
        Vector3 localPos =  new Vector3
                                        (
                                            10 * Mathf.Sin(30 * Mathf.Deg2Rad), 
                                            0, 
                                            10 * Mathf.Cos(30 * Mathf.Deg2Rad)
                                        );
        //TransformPoint()将点从自身坐标系转换到世界坐标系,在自身坐标系中物体自身就是原点
        Vector3 worldPos = transform.TransformPoint(localPos);

        Debug.DrawLine(transform.position, worldPos);
	}
	

四元数法

    private void Demo01()
    {  
        //计算物体右前方30度10m处坐标
        Vector3 worldPos =
            transform.position + Quaternion.Euler(0, 30, 0) * transform.rotation * new Vector3(0, 0, 10);

        Debug.DrawLine(transform.position, worldPos);
    }

练习二:计算炸弹范围的判定(切点Demo)

在这里插入图片描述在这里插入图片描述

using UnityEngine;
using System.Collections;

/// <summary>
/// 切点探测器
/// </summary>
public class TangentDetector : MonoBehaviour
{
    private Vector3 leftTangent;
    private Vector3 rightTangent;

    private Transform playerTF;
    private float radius;
    private void Start()
    {
        GameObject playerGO  = GameObject.FindWithTag("Player");
        if (playerGO != null)
        {
            playerTF = playerGO.transform;
            radius = playerGO.GetComponent<CapsuleCollider>().radius;
        }
        else
        {
            this.enabled = false;
        }
    }

    public void CalaculateTangent()
    {
        Vector3 playerToExplosion = transform.position - playerTF.position;
        Vector3 playerToExplosionRadius = playerToExplosion.normalized * radius;
        float angle = Mathf.Acos(radius / playerToExplosion.magnitude) * Mathf.Rad2Deg;
        rightTangent =playerTF .position + Quaternion.Euler(0, angle, 0) * playerToExplosionRadius;
        leftTangent = playerTF.position + Quaternion.Euler(0, -angle, 0) * playerToExplosionRadius;
    }

    //**************测试**************
    private void Update()
    {
        CalaculateTangent();

        Debug.DrawLine(transform.position, leftTangent);
        Debug.DrawLine(transform.position, rightTangent);
    }
}

练习三:根据用户输入的方向旋转角色,并向前移动

重点->vector3.forward和transform.forward的区别

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
///
/// </summary>
public class CharcterMoto : MonoBehaviour 
{
    public float moveSpeed = 10;
    public float rotateSpeed = 10;
    private void Update()
    {
        float RL = Input.GetAxis("Horizontal");
        float UD = Input.GetAxis("Vertical");

        if (RL != 0 || UD != 0)
            RotateView(RL, UD);

    }

    private void RotateView(float RL, float UD)
    {

        //创建一个向量,注视旋转,让自身的z轴对着这个向量。
        Quaternion dir = Quaternion.LookRotation(new Vector3(RL, 0, UD));
        //transform.rotation = dir;
        //Lerp的使用,使得旋转更加自然。
        transform.rotation = Quaternion.Lerp(transform.rotation, dir, rotateSpeed * Time.deltaTime);
        //方法一:
        transform.position += transform.forward * moveSpeed * Time.deltaTime;
        //方法二:
        //Translate中默认是移动被应用相对于自身轴,简单来说默认物体相对于自身向某方向移动多少距离,若规定Space.World则是相对于世界坐标。
        //transform.Translate(0, 0, moveSpeed * Time.deltaTime);
        //方法三
        //transform.Translate(transform.forward * Time.deltaTime * moveSpeed, Space.World);

    }

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值