四元素-Quaternion

<p>
回顾一下四元素中的属性和方法。
</p>

属性:

public Vector3 eulerAngles
功能说明 此属性用来返回或设置Quaternion实例对应的欧拉角
进行赋值的方式通常有两种:

public Transform A, B;
Quaternion rotations=Quaternion.identity;
Vector3 eulerAngle = Vector3.zero;

第一种是将Quaternion实例赋值给transform的rotation 
rotations.eulerAngles = new Vector3(0.0f, speed * Time.time, 0.0f);
A.rotation = rotations;

第二种是将三维向量代表的欧拉角直接赋值给transform的eulerAngles
eulerAngle = new Vector3(0.0f, speed * Time.time, 0.0f);
B.eulerAngles = eulerAngle;

Quaternion类实例方法:

在Quaternion类中涉及的实例方法有SetFromToRotation方法、SetLookRotation方法和ToAngleAxis方法

SetFromToRotation方法

public void SetFromToRotation(Vector3 fromDirection, Vector3 toDirection);
用于创建一个从fromDirection到toDirection的rotation,同样也不能够直接对Transform.rotation直接进行操作,先对四元素进行旋转,然后将四元素赋值给rotation,例如:

//不可直接使用transform.rotation.SetFromToRotation(v1,v2)方式进行设置
//只能将实例化的Quaternion赋值给transform.rotation。
Quaternion q1 = Quaternion.identity;
q1.SetFromToRotation(v1,v2);
transform.rotation = q1;

首先会把该物体的xyz轴方向和世界坐标的xyz一致(即rotation在世界坐标系中为0,如果是父对象有旋转的话也不影响),然后旋转的rotation为:V1指向的方向旋转到V2指向的方向:

image.png

A为v1,B为V2,如果B向上移动一定距离,那么C也会朝上旋转;

SetLookRotation方法

基本语法
(1) public void SetLookRotation(Vector3 view);
(2) public void SetLookRotation(Vector3 view, Vector3 up);
用来对一个Quaternion实例的朝向进行设置。例如:

Quaternion q1 = Quaternion.identity;
q1.SetLookRotation(v1); //1.
q1.SetLookRotation(v1, v2); //2.
transform.rotation = q1;

q1.SetLookRotation(v1):transform.right垂直于由Vector3.zero、v1、v1.up构成的平面,transform.forward为v1向量,下图中A为v1:

image.png

q1.SetLookRotation(v1, v2):
transform.right垂直于由Vector3.zero、v1和v2这3点构成的平面。
v2除了与Vector3.zero和v1构成平面来决定transform.right的方向外,还用来决定transform.up的朝向,因为当transform.forward和transform.right方向确定后, transform.up方向剩下两种可能,到底选用哪一种便由v2来影响。transform.up方向的选取方式总会使得transform.up的方向和v2方向的夹角小于或等于90度。

image.png

当v1为Vector3.zero时,方法失效,即不要在使用此方法时把v1设置成Vector3.zero。
<pre>
提示
不可以直接使用transform.rotation.SetLookRotation(v1, v2)的方式来使用SetLookRotation方法,否则会不起
作用。应该使用上述代码所示的方式,首先实例化一个Quaternion,然后对其使用SetLookRotation,最后将其赋给transform.rotation。
</pre>

ToAngleAxis方法

基本语法
public void ToAngleAxis(out float angle, out Vector3 axis);
其中参数angle为旋转角,参数axis为轴向量。
功能说明 此方法用于将Quaternion实例转换为角轴表示。
在transform.rotation.ToAngle Axis(out angle, out axis)中,输出值angle和axis的含义为:要将GameObject对象的rotation从Quaternion.Identity状态变换到当前状态,只需要将GameObject对象绕着axis的轴向(指世界坐标系中)旋转angle角度即可。通常和静态方法AngleAxis (angle : float, axis : Vector3)联合使用,使得一个物体的rotation始终和另一个物体的rotation保持一致,例如:

void Update()
    {
        //使用ToAngleAxis获取A的Rotation的旋转轴和角度
        A.rotation.ToAngleAxis(out angle, out axis);
        //使用AngleAxis设置B的rotation,使得B的rotation状态的和A相同
        //当然也可以只使得B与A的axis相同,而angle不同
        //可以在程序运行时修改A的rotation查看B的状态
        B.rotation = Quaternion.AngleAxis(angle, axis);
    }

运行效果如下,B会随着A的旋转保持和A一致:

image.png

Quaternion类静态方法

在Quaternion类中主要的静态方法有Angle方法、Dot方法、Euler方法、FromToRotation方法、Inverse方法、Lerp方法、LookRotation方法、RotateTowards方法和Slerp方法:

Angle方法:Quaternion实例间夹角

基本语法 public static float Angle(Quaternion a, Quaternion b);
功能说明 此方法用于返回从参数a到参数b变换的夹角。需要注意的是,返回的夹角不是某个局部坐标轴向变换的夹角,而是GameObject对象从状态a转换到状态b时需要旋转的最小夹角。

Dot方法:点乘

基本语法 public static float Dot(Quaternion a, Quaternion b);
a●b=|a||b|cos夹角 可以判断a在b的前方和后方.

Euler方法:欧拉角对应的四元数

基本语法
(1) public static Quaternion Euler(Vector3 euler);
(2) public static Quaternion Euler(float x, float y, float z);
功能说明 此方法用于返回欧拉角Vector3(x,y,z)对应的四元数Quaternion实例。

FromToRotation方法:Quaternion变换

基本语法
public static Quaternion FromToRotation(Vector3 fromDirection, Vector3 toDirection);
功能说明 此方法用来创建一个从参数fromDirection到toDirection的Quaternion变换。其功能和实例方法SetFromToRotation (fromDirection : Vector3, toDirection : Vector3)相同:
测试代码如下:

 void Update()
    {
        //使用实例方法
        //不可直接使用C.rotation.SetFromToRotation(A.position,B.position);
        q1.SetFromToRotation(A.position, B.position);
        C.rotation = q1;
        //使用类方法
        D.rotation = Quaternion.FromToRotation(A.position, B.position);
        //在Scene视图中绘制直线
        Debug.DrawLine(Vector3.zero, A.position, Color.white);
        Debug.DrawLine(Vector3.zero, B.position, Color.white);
        Debug.DrawLine(C.position, C.position + new Vector3(0.0f, 1.0f, 0.0f),
        Color.white);
        Debug.DrawLine(C.position, C.TransformPoint(Vector3.up * 1.5f), Color.white);
        Debug.DrawLine(D.position, D.position + new Vector3(0.0f, 1.0f, 0.0f),
        Color.white);
        Debug.DrawLine(D.position, D.TransformPoint(Vector3.up * 1.5f), Color.white);
    }
AB夹角.png

C和D的旋转角度:

旋转角度.png
Inverse方法:逆向Quaternion值

基本语法
public static Quaternion Inverse(Quaternion rotation);

功能说明 此方法用于返回参数rotation的逆向Quaternion值。例如,设有实例rotation=(x,y,z,w),则Inverse(rotation)=(-x,-y,-z,w)。从效果上说,设rotation.eulerAngles=(a,b,c),则transform.rotation=Inverse(rotation)相当于transform依次绕自身坐标系的z轴、x轴和y轴分别旋转-c度、-a度和-b度。由于是局部坐标系内的变换,最后transform的欧拉角的各个分量值并不一定等于-a、-b或-c。
示例:
代码如下:

 public Transform A, B;
    void Start()
    {
        Quaternion q1 = Quaternion.identity;
        Quaternion q2 = Quaternion.identity;
        q1.eulerAngles = new Vector3(0, -90, 0);
        q2 = Quaternion.Inverse(q1);
        A.rotation = q1;
        B.rotation = q2;
    }

运行后的结果如下(Cube蓝色为正面):

结果.png
Lerp方法:线性插值

基本语法
public static Quaternion Lerp(Quaternion from, Quaternion to, float t);
功能说明 此方法用于返回从参数from到to的线性插值。当参数t≤0时返回值为from,当参数t≥1时返回值为to。此方法执行速度比Slerp方法快,一般情况下可代替Slerp方法。

示例:
代码如下:


public Transform A, B, C, D;
float speed = 0.2f;
void Update()
{
C.rotation = Quaternion.Slerp(A.rotation, B.rotation, Time.time * speed);
D.rotation = Quaternion.Lerp(A.rotation, B.rotation, Time.time * speed);

运行时会发现,C和D会渐渐由A的rotation旋转到B的rotation:

运行结果.png
LookRotation方法:设置Quaternion的朝向(和类实例方法SetLookRotation 类似,可以往上查看实例方法)

基本语法
(1) public static Quaternion LookRotation(Vector3 forward);
(2) public static Quaternion LookRotation(Vector3 forward, Vector3 upwards);

其中参数forward为返回Quaternion的forward朝向。
功能说明 此方法用于返回一个Quaternion实例,使GameObject对象的z轴朝向参数forward方向(使GameObject的forward为参数的向量)。此方法与方法SetLookRotation (view : Vector3, up : Vector3 = Vector3.up)功能相同。

RotateTowards方法:Quaternion插值

基本语法
public static Quaternion RotateTowards(Quaternion from, Quaternion to, float maxDegreesDelta);
其中参数from为起始Quaternion,参数to为结束Quaternion,参数maxDegreesDelta为每帧最大角度值。

功能说明 此方法用于返回从参数from到to的插值,且返回值的最大角度不超过maxDegreesDelta。此方法功能与方法Slerp相似,只是maxDegreesDelta指的是角度值,不是插值系数。当maxDegreesDelta<0时,将沿着从to到from的方向插值计算。

Quaternion类运算符

在Quaternion类中涉及的运算符运算有两个Quaternion实例相乘的运算、一个Quaternion实例和一个Vector3相乘的运算。

两个Quaternion实例相乘的运算

功能说明 此运算符用于返回两个Quaternion实例相乘后的结果。设A和B均为GameObject对象的一个实例,有如下代码:
B.rotation *= A.rotation;

代码每执行一次,B都会绕着B的局部坐标系的z、x、y轴分别旋转A.eulerAngles.z度、A.eulerAngles.x度和A.eulerAngles.y度,注意它们的旋转次序一定是先饶z轴再绕x轴最后绕y轴进行相应的旋转。另外由于是绕着局部坐标系旋转,故而当绕着其中一个轴旋转时,很可能会影响其余两个坐标轴方向的欧拉角(除非其余两轴的欧拉角都为0才不受影响)。

一个Quaternion实例和一个Vector3相乘的运算

功能说明 此运算符的作用是对参数坐标点point进行rotation变换。例如,设A为Vector3实例,有如下代码:

transform.position += transform.rotation *A;
则每执行一次代码,transform对应的对象便会沿着自身坐标系中向量A的方向移动A的模长的距离。transform.rotation与A相乘主要来确定移动的方向和距离。

推荐阅读更多精彩内容