Please enable Javascript to view the contents

Unity3d获取与Inspector面板Rotation一样的欧拉角

 ·  ☕ 5 分钟  ·  ✍️ YSL

unity 中的为了任意方位都只有独一无二的表示 欧拉角范围 x [-90,90] y,z [0,360] unity 超过范围unity 会转化
使用transform.localEulerAngles.x或transform.rotation.eulerAngles.x输出的欧拉角与Inspector面板中的Rotation值是不一样的。

原因:Inspector面板中的Rotation值系统做了转化处理,而不是直接取的欧拉角。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
    private void OutputInpectorEulers()
    {
        Vector3 angle = transform.eulerAngles;
        float x = angle.x;
        float y = angle.y;
        float z = angle.z;
 
        if (Vector3.Dot(transform.up, Vector3.up) >= 0f)
        {
            if (angle.x >= 0f && angle.x <= 90f)
            {
                x = angle.x;
            }
            if (angle.x >= 270f && angle.x <= 360f)
            {
                x = angle.x - 360f;
            }
        }
        if (Vector3.Dot(transform.up, Vector3.up) < 0f)
        {
            if (angle.x >= 0f && angle.x <= 90f)
            {
                x = 180 - angle.x;
            }
            if (angle.x >= 270f && angle.x <= 360f)
            {
                x = 180 - angle.x;
            }
        }
 
        if (angle.y > 180)
        {
            y = angle.y - 360f;
        }
 
        if (angle.z > 180)
        {
            z = angle.z - 360f;
        }
 
        Debug.Log(" Inspector Euler:  " + Mathf.Round(x) + " , " + Mathf.Round(y) + " , " + Mathf.Round(z));
    }

Unity中欧拉角
什么是欧拉角?

(1)使用单个角度来保存方位

(2)X与Z沿自身坐标系旋转,Y沿世界坐标旋转

(3)API:Vector3 eulerAngle =this.tranform.rulerAngles;

优点:

(1)仅使用三个数字表达方位,占用空间小

(2)沿坐标轴旋转的单位维角度,符合人的思考方式

(3)任意三个数字都是合法的,不存在不合法的欧拉角

缺点:

(1)方位的表达方式不唯一

对于一个方位,存在多个欧拉角描述,因此无法判断多个欧拉角代表的角唯一是否相同

例如

–角度0,5,0和角度0,365,0

–角度0,-5,0和角度0,355,0

–角度250,0,0与角度290,180,180

为了保证任意方位都只有独一无二的表示,Unity引擎限制了角度范围,即沿X轴旋转限制在-90到90之间(圆的270度到90度,代码运行可以看出),沿Y与Z轴旋转限制在0到360之间

缺点:对于一个方位,存在多个欧拉角描述,因此无法判断多个欧拉角代表的角位移是否相同。比如(250,0,0)与(290,180,180)为同一个欧拉角,为了保证任意方位都只有独一无二的表示,Unity引擎限制了角度范围,即沿X轴旋转限制在-90到90之间,沿Y与Z轴 旋转限制在0到360之间。

(2)万向节死锁

物体沿X轴旋转+-90度,自身坐标系Z轴与世界坐标系Y轴将重合,此时沿Z或Y旋转时,将失去一个自由度

在万向节死锁情况下,规定沿Y轴完成绕竖直轴的全部旋转,则此时Z轴旋转为0

欧拉角
使用三个数字来保存方位(描述物体的朝向),使用Vector3存储但并不代表向量;代表一系列的三维基本旋转,也就是围绕一个坐标系的每个轴的一系列旋转。
仅使用三个数字表达方位,占用空间小
优点:三个角度(沿坐标轴旋转的单位)组成,直观,容易理解。
优点:可以进行从一个方向到另一个方向旋转大于180度的角度。
缺点:万向节死锁问题。
缺点:对于一个方位,存在多个欧拉角描述,因此无法判断多个欧拉角代表的角位移是否相同。比如(250,0,0)与(290,180,180)为同一个欧拉角,为了保证任意方位都只有独一无二的表示,Unity引擎限制了角度范围,即沿X轴旋转限制在-90到90之间,沿Y与Z轴 旋转限制在0到360之间。
欧拉角分类
静态:即绕世界坐标系三个轴的旋转,由于物体旋转过程中坐标轴保持静止,所以称为静态
动态:即绕物体坐标系的三个轴的旋转,由于物体的旋转过程中坐标轴随着物体做着相同的旋转,所以称之为动态(存在万向节死锁问题)

使用transform.localEulerAngles.x或transform.rotation.eulerAngles.x输出的欧拉角与Inspector面板中的Rotation值是不一样的。

原因:Inspector面板中的Rotation值系统做了转化处理,而不是直接取的欧拉角。

复制代码
private void OutputInpectorEulers()
{
Vector3 angle = transform.eulerAngles;
float x = angle.x;
float y = angle.y;
float z = angle.z;

    if (Vector3.Dot(transform.up, Vector3.up) >= 0f)
    {
        if (angle.x >= 0f && angle.x <= 90f)
        {
            x = angle.x;
        }
        if (angle.x >= 270f && angle.x <= 360f)
        {
            x = angle.x - 360f;
        }
    }
    if (Vector3.Dot(transform.up, Vector3.up) < 0f)
    {
        if (angle.x >= 0f && angle.x <= 90f)
        {
            x = 180 - angle.x;
        }
        if (angle.x >= 270f && angle.x <= 360f)
        {
            x = 180 - angle.x;
        }
    }

    if (angle.y > 180)
    {
        y = angle.y - 360f;
    }

    if (angle.z > 180)
    {
        z = angle.z - 360f;
    }

    Debug.Log(" Inspector Euler:  " + Mathf.Round(x) + " , " + Mathf.Round(y) + " , " + Mathf.Round(z));
}

复制代码

为什么Unity3d旋转默认采用了有万向节死锁的欧拉角,而不用四元数?
Unity的底层是通过四元数记录物体旋转的,并通过矩阵和四元数实现物体的旋转及插值。

但在上层Unity提供了,向欧拉角进行转换输出,并能够通过欧拉角进设置物体旋转的功能。

一些本通过四元数进行旋转/插值计算的方法,在上层也是通过欧拉角输入对应旋转值。

这是由于相较矩阵和四元数,欧拉角是最接近人类直观思维的一种3D旋转表达模式,应该没有人想通过输入矩阵或者四元数来旋转物体吧…

在底层通过矩阵/四元数,记录完成旋转,避免万向锁,但在上层提供欧拉角的转换输出和旋转设定,这应该说是当下大多数3D引擎架构都普遍采用的一种模式。

此外还要提两点的:

一是,限制欧拉角;

由于存在 四元数—>欧拉角 这样的底层到上层的转换输出,因而就需要引入限制欧拉角规则。

这是由于三角函数是一个周期函数,因而我们进行反三角函数运算的时候,要将输出值限制在一定的范围内,否则会有无穷多解。

其实这也是由于欧拉角的一大缺点之一,因为±360度角度值相同,导致对于同一3D方位/角位移会有无数种表示。

Unity中的欧拉角采用 Y(Heading)–>X(Pitch)–>Z(Bank) 的轴顺序,对应的限制规则,是将Y和Z轴的旋转数值限制在[-180,180],中间X轴旋转数值限制在[-90,90]。

总之就是内外转轴360度全域,中间转轴只有180度半域。

这里给出指定欧拉角的旋转矩阵:

todo 。。。。

整理总结: https://blog.csdn.net/dmk17771552304/article/details/120110629