Unity流水账3:旋转

Quaternion(四元数)
四元数用来表示旋转。他们紧凑,不受万向锁的困扰,而且容易插值。Unity内部使用四元数来表示所有的旋转。它们是基于复数的,不容易直观理解。你几乎从未访问或修改过单个四元数组件(x,y,z,w);通常情况下,你只需要使用现有的rotations来构造新的旋转(例如在两个旋转之间平滑的插值)。你99%的时间使用的四元数函数是:
Quaternion.LookRotation,Quaternion.Angle,Quaternion.Euler,Quaternion.Slerp,Quaternion.FromToRotation 以及Quaternion.identity.(其他功能仅用于特殊用途)。
你可以使用Quaternion.operator *将一个旋转转换到另一个,或者通过一个旋转,旋转一个向量。
注意:Unity期望四元数被标准化

Static Properties

identity:同一性旋转(只读)。该四元数,相当于无旋转,这个物体完全对齐于世界或父轴。
函数定义:public static Quaternion identity;
代码示例:
using UnityEngine;
public class rotateTest:MonoBehaviour
{
	void Start()
	{
		//此时transform的坐标轴与世界坐标轴一致
		transform.rotate = Quaternion.identity;
	}
}

Properties

eulerAngles:返回旋转的欧拉角表示(2017.4.3f已弃用),围绕z轴旋转euler.z度,围绕x轴旋转euler.x度,围绕y轴旋转euler.y度(按照此顺序).可以为四元数设置或读取euler.
函数定义:public Vector3 eulerAngles;
代码示例:
using UnityEngine;

public class rotateTest : MonoBehaviour {
    private Quaternion quaternion;
    private GameObject cube;
    private float timeCount = 0.0f;
    private void Awake()
    {
        quaternion = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
        cube = CreateCube();
    }
    private void Update()
    {
        if(timeCount > 2.0f)
        {
            quaternion = Random.rotation;
            cube.transform.rotation = quaternion;
            timeCount = 0.0f;
        }
        timeCount = timeCount + Time.deltaTime;
    }
    private void OnGUI()
    {
        GUIStyle style = new GUIStyle();
        style.fontSize = 24;
        Vector3 angles = quaternion.eulerAngles;
        GUI.Label(new Rect(10, 10, 0, 0), angles.ToString("F3"), style);
        //GUI.Label(new Rect(10, 90, 250, 50), cube.transform.localEulerAngles.ToString("F3"));
    }
    private GameObject CreateCube()
    {
        GameObject newCube = new GameObject("Cube");

        GameObject minusZ = GameObject.CreatePrimitive(PrimitiveType.Quad);
        minusZ.transform.position = new Vector3(0.0f, 0.0f, -0.5f);
        minusZ.GetComponent<Renderer>().material.color = Color.gray;
        minusZ.transform.parent = newCube.transform;

        GameObject plusZ = GameObject.CreatePrimitive(PrimitiveType.Quad);
        plusZ.transform.position = new Vector3(0.0f, 0.0f, 0.5f);
        plusZ.transform.Rotate(new Vector3(0.0f, 180.0f, 0.0f));
        plusZ.GetComponent<Renderer>().material.color = Color.magenta;
        plusZ.transform.parent = newCube.transform;

        GameObject minusX = GameObject.CreatePrimitive(PrimitiveType.Quad);
        minusX.transform.position = new Vector3(0.5f, 0.0f, 0.0f);
        minusX.transform.Rotate(new Vector3(0.0f, 270.0f, 0.0f));
        minusX.GetComponent<Renderer>().material.color = Color.yellow;
        minusX.transform.parent = newCube.transform;

        GameObject plusX = GameObject.CreatePrimitive(PrimitiveType.Quad);
        plusX.transform.position = new Vector3(-0.5f, 0.0f, 0.0f);
        plusX.transform.Rotate(new Vector3(0.0f, 90.0f, 0.0f));
        plusX.GetComponent<Renderer>().material.color = Color.blue;
        plusX.transform.parent = newCube.transform;

        GameObject minusY = GameObject.CreatePrimitive(PrimitiveType.Quad);
        minusY.transform.position = new Vector3(0.0f, -0.5f, 0.0f);
        minusY.transform.Rotate(new Vector3(270.0f, 0.0f, 0.0f));
        minusY.GetComponent<Renderer>().material.color = Color.green;
        minusY.transform.parent = newCube.transform;

        GameObject plusY = GameObject.CreatePrimitive(PrimitiveType.Quad);
        plusY.transform.position = new Vector3(0.0f, 0.5f, 0.0f);
        plusY.transform.Rotate(new Vector3(90.0f, 0.0f, 0.0f));
        plusY.GetComponent<Renderer>().material.color = Color.red;
        plusY.transform.parent = newCube.transform;

        return newCube;
    }
}
normalized:返回模为1的四元数(只读)。归一化时,四元数保持相同的方向,但其大小为1.0。注意:当前四元数未更改,并返回新的归一化的四元数。如果想要归一化原始的四元数,改用Normalize方法。如果四元数太小,以至于无法归一化,则将返回Quaternion.identity。
函数定义:
public Quaternion normalized;
this[int]:分别使用[0],[1],[2],[3]访问x,y,z,w分量
函数定义:
public float this[int]
代码示例:
using UnityEngine;

public class rotateTest : MonoBehaviour {
    private void Start()
    {
        Quaternion p = new Quaternion();
        Debug.Log(p);
        p[3] = 0.5f; //等价于p.w = 0.5f
        Debug.Log(p);
    }
}
输出为:
(0.0,0.0,0.0,0.0)
(0.0,0.0,0.0,0.5)
w:四元数的w分量,不要直接修改它,除非你完全了解四元数
函数定义:public float w;
w:四元数的w分量,不要直接修改它,除非你完全了解四元数.四元数可以表示3D旋转,并由4个实数定义。x,y,z表示一个向量。w是一个标量用于存储绕向量的旋转角度(cos(θ/2))
函数定义:public float w;
代码示例:
using UnityEngine;
public class rotateTest : MonoBehaviour {
    private float timeDelay = 0.0f;
    private Quaternion q;
    private string label = "";
    private void Awake()
    {
        GameObject line = GameObject.CreatePrimitive(PrimitiveType.Cube);
        line.transform.localScale = new Vector3(0.05f, 1.5f, 0.05f);
        line.transform.parent = gameObject.transform;
    }
    private void Update()
    {
        if(timeDelay > 1.0f)
        {
            Vector3 v;
            v.x = Random.Range(0.0f, 360.0f);
            v.y = Random.Range(0.0f, 360.0f);
            v.z = Random.Range(0.0f, 360.0f);
            q = Quaternion.Euler(v);
            transform.rotation = q;
            label = q.ToString("f3");
            timeDelay = 0.0f;
        }
        timeDelay += Time.deltaTime;
    }
    private void OnGUI()
    {
        GUI.skin.label.fixedHeight = 40;
        GUI.skin.label.fontSize = 24;
        GUI.Label(new Rect(10, 10, 400, 30), label);
    }
}
设旋转轴为v,旋转角为a则x = sin(a/2)v.x,y = sin(a/2)v.y,z = sin(a/2)v.z
x:四元数的x分量,不要直接修改它,除非你完全了解四元数
y:四元数的y分量,不要直接修改它,除非你完全了解四元数
z:四元数的z分量,不要直接修改它,除非你完全了解四元数
函数定义:
public float x;
public float y;
public float z;
代码示例:
using UnityEngine;
using UnityEngine.UI;

public class rotateTest : MonoBehaviour {
    float m_MyX, m_MyY, m_MyZ;
    public Slider m_SlidersX, m_SliderY, m_SliderZ;
    public Text m_TextX, m_TextY, m_TextZ;
    private void Start()
    {
        m_MyX = 0;
        m_MyY = 0;
        m_MyZ = 0;
        m_SlidersX.maxValue = 1;
        m_SliderY.maxValue = 1;
        m_SliderZ.maxValue = 1;
        m_SlidersX.minValue = -1;
        m_SliderY.minValue = -1;
        m_SliderZ.minValue = -1;
    }
    private static Quaternion Change(float x, float y,float z)
    {
        return new Quaternion(x, y, z, 1);
    }
    private void Update()
    {
        m_MyX = m_SlidersX.value;
        m_MyY = m_SliderY.value;
        m_MyZ = m_SliderZ.value;
        m_TextX.text = " X : " + m_MyX;
        m_TextY.text = " Y : " + m_MyY;
        m_TextZ.text = " Z : " + m_MyZ;
        transform.rotation = Change(m_MyX, m_MyY, m_MyZ);
    }
}

Constructors

Quaternion:用给定的x,y,z,w分量构造新的四元数
函数定义:public Quaternion(float x,float y,float z,float w)

Public Methods

Set:设置现有四元数的x,y,z和w分量
函数定义:
public void Set(float newX,float newY,float newZ,float newW);
SetFromToRotation:创建一个从一个方向旋转到另一个方向的旋转。使用此选项创建一个从第一个向量开始并旋转到第二个向量的旋转。
函数定义:
public void SetFromToRotation(Vector3 fromDirection,Vector3 toDirection)
代码示例1:
using UnityEngine;

public class rotateTest : MonoBehaviour {
    public Transform m_NextPoint;
    Quaternion m_MyQuaternion;
    float m_Speed = 1.0f;
    private void Start()
    {
        m_MyQuaternion = new Quaternion();
    }
    private void Update()
    {
        Debug.DrawLine(Vector3.zero, transform.position, Color.red);
        Debug.DrawLine(Vector3.zero, m_NextPoint.position, Color.green);
        Vector3 crossVector = Vector3.Cross(transform.position, m_NextPoint.position);
        Debug.DrawLine(Vector3.zero, crossVector,Color.black);
        Debug.DrawLine(transform.position, transform.position + crossVector, Color.cyan);
        //绕原点指向transform.position的向量A以及原点指向m_NextPoint.position的向量B组成的平面的垂直线旋转A到B的夹角
        m_MyQuaternion.SetFromToRotation(transform.position, m_NextPoint.position);
        transform.position = Vector3.Lerp(transform.position, m_NextPoint.position, m_Speed * Time.deltaTime);
        //从世界坐标轴旋转至transform位置,然后在旋转到m_NextPoint的位置
        transform.rotation = m_MyQuaternion * transform.rotation;
    }
}
代码示例2:
using UnityEngine;

public class rotateTest : MonoBehaviour {
    Quaternion m_MyQuaternion;
    float m_Speed = 1.0f;
    Vector3 m_MousePosition;
    private void Start()
    {
        m_MyQuaternion = new Quaternion();
    }
    private void Update()
    {
        m_MousePosition = Input.mousePosition;
        m_MousePosition.z = 50.0f;
        m_MousePosition = Camera.main.ScreenToWorldPoint(m_MousePosition);
        m_MyQuaternion.SetFromToRotation(transform.position, m_MousePosition);
        transform.position = Vector3.Lerp(transform.position, m_MousePosition, m_Speed * Time.deltaTime);
        transform.rotation = m_MyQuaternion * transform.rotation;
    }
}
SetLookRotation:创建一个旋转,沿着forward(z轴)并且头部沿着up(y轴)的约束注视。也就是建立一个旋转,使z轴朝向view,y轴朝向up)。如果forward方向是0,记录一个错误。
函数定义:public void SetLookRotation(Vector3 view,Vector3 up = Vector3.up);
函数参数:
1.view:朝向的方向
2.up:定义up方向
ToAngleAxis:将旋转转换为角轴表示(角度单位)
函数参数:public void ToAngleAxis(out float angle,out Vector3 axis)
代码示例1:
using UnityEngine;

public class rotateTest : MonoBehaviour
{
    private void Start()
    {
        float angle = 0.0f;
        Vector3 axis = Vector3.zero;
        //绕世界坐标轴Y轴顺时针(左手坐标系)旋转90度:则旋转轴(0,1,0),a = 90;即四元数为(sin(a/2) * 0,sin(a/2) * 1,sin(a/2) * 0,con(a/2));
        Quaternion A = new Quaternion(0, 0.525f, 0, 0.525f);
        //绕世界坐标轴X轴顺时针(左手坐标系)旋转90:则旋转轴为(1,0,0),a = 90
        Quaternion B = new Quaternion(0.525f, 0, 0, 0.525f);
        //transform绕世界坐标轴Y轴顺时针旋转90度,然后绕世界坐标轴X轴顺时针旋转90度
        //由于transform绕世界坐标轴Y轴顺时针旋转90度后transform的模型坐标轴:X轴对应世界坐标轴-Z轴,Z轴对应世界坐标轴X轴,Y轴对应世界坐标轴Y轴
        //则绕世界坐标轴X轴顺时针旋转90度相当于绕模型坐标轴Z轴旋转90.
        transform.rotation = B * A;
        transform.rotation.ToAngleAxis(out angle, out axis);
        Debug.Log(angle + ":" + axis);
        float halfRadians = Mathf.Acos(transform.rotation.w);
        float halfSin = Mathf.Sin(halfRadians);
        Debug.Log(halfRadians * Mathf.Rad2Deg * 2 + ":" + transform.rotation.x / halfSin + ":" + transform.rotation.y / halfSin + ":" + transform.rotation.y / halfSin);
        Debug.Log(transform.eulerAngles);
    }
}
代码示例2:
using UnityEngine;

public class RotateTest : MonoBehaviour
{
    public Transform target1;
    public Transform target2;
    float angle;
    void Start()
    {
    }
    private void Update()
    {
        //万向锁
        //在Inspector面板的Transfomr组件中输入R:X = 90, Y = 0, Z = 0;然后随意修改Y值和Z值可以发现无论修改Y值还是Z值,
        //模型都只能绕着模型坐标轴的Z轴或-Z轴进行旋转,无法再通过修改Y值或者Z值来达到绕着Y轴旋转的目的,这就是万向锁问题
        //这是由于Unity的旋转顺序是Y-X-Z,设此时绕Y轴的选择为QY,绕X轴的旋转为QX,绕Z轴的旋转为QZ则此时的旋转变化为
        //transform.rotation = QZ * QX * QY,则物体绕世界坐标轴Y轴进行旋转变化QY,然后在进行QY旋转变化后的坐标轴进行变化QX
        //由于此时的QX变化导致了模型坐标轴Z轴与世界坐标轴-Y轴重叠
        //从而导致改变Y值与改变Z值,模型都只能绕着模型坐标轴的Z轴或-Z轴进行旋转。
        target1.localRotation = Quaternion.identity;
        target1.Rotate(new Vector3(0, angle, 0), Space.Self);
        target1.Rotate(new Vector3(90, 0, 0), Space.Self);
        target2.localRotation = Quaternion.identity;
        target2.Rotate(new Vector3(90, 0, 0), Space.Self);
        target2.Rotate(new Vector3(0, 0, angle), Space.Self);
        angle = angle + 1;
        if (angle > 360)
            angle = 0;
    }
}
ToString:返回一个格式良好的四元数字符串
函数定义:
public string ToSTring();
public string ToString(string format);
代码示例:
using UnityEngine;

public class rotateTest : MonoBehaviour {
    private void Start()
    {
        print(Quaternion.identity);
    }
}

Static Methods

Angle:返回两个旋转a和b之间的角度
函数定义:
public static float Angle(Quaternion a,Quaternion b);
代码示例:
using UnityEngine;
public class rotateTest : MonoBehaviour {
    public Transform target;
    private void Start()
    {
        //想象两个游戏对象(A和B)围绕第三个GameObject(C)移动。
        //从C到A和C到B的线创建一个可以随时间变化的三角形.CA和CB之间的角度是Quaternion.Angle提供的值
        //public static float Dot(Quaternion a, Quaternion b)
        //{
        //return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;
        //}
        //public static float Angle(Quaternion a, Quaternion b)
        //{
        //float dot = Dot(a, b);
        //return IsEqualUsingDot(dot) ? 0.0f : Mathf.Acos(Mathf.Min(Mathf.Abs(dot), 1.0F)) * 2.0F * Mathf.Rad2Deg;
        //}
    float angle = Quaternion.Angle(transform.rotation, target.rotation);
        float dot = transform.rotation.x * target.rotation.x + transform.rotation.y * target.rotation.y + transform.rotation.z * target.rotation.z
            + transform.rotation.w * target.rotation.w;
        Debug.Log(angle + ":" + dot);
    }
}
AngleAxis:创建一个围绕轴旋转某个角度的旋转
函数定义:
public static Quaternion AngleAxis(flaot angle,Vector3 axis);
代码示例:
using UnityEngine;

public class rotateTest : MonoBehaviour {
    private void Start()
    {
        //绕世界坐标轴y轴顺时针旋转30度
        transform.rotation = Quaternion.AngleAxis(30, Vector3.up);
    }
}
Dot:两个旋转之间的点积
函数定义:
public static float Dot(Quaternion a,Quaternion b);
代码示例:
using UnityEngine;

public class rotateTest : MonoBehaviour {
    private void Start()
    {
        float dot1 = Quaternion.Dot(transform.rotation, Quaternion.identity);
        float dot2 = transform.rotation.x * Quaternion.identity.x + transform.rotation.y * Quaternion.identity.y + transform.rotation.z * Quaternion.identity.z
            + transform.rotation.w * transform.rotation.w;
        Debug.Log(Quaternion.identity + ":" + dot1 + ":" + dot2);
    }
Euler:返回绕z轴旋转z度,绕x轴旋转x度,绕y轴旋转y度的旋转
函数定义:
1.public static Quaternion Euler(float x, float y, float z)
2.public static Quaternion Euler(Vector3 euler);
代码示例1:
using UnityEngine;

public class rotateTest : MonoBehaviour {
    private void Start()
    {
        //绕世界坐标轴Y轴顺时针旋转30度
        Quaternion rotation = Quaternion.Euler(0, 30, 0);
        transform.rotation = rotation;
    }
}
代码示例2:
using UnityEngine;

public class rotateTest : MonoBehaviour {
    private void Start()
    {
        //绕世界坐标轴Y轴顺时针旋转30度
        Vector3 rotationVector = new Vector3(0, 30, 0);
        Quaternion rotation = Quaternion.Euler(rotationVector);
        transform.rotation = rotation;
    }
}
FromToRotation:创建一个从一个方向旋转到另一个方向的旋转,见SetFromToRotation
函数定义:
public static Quaternion FromToRation(Vector3 fromDirection,Vector3 toDirection);
代码示例:
using UnityEngine;

public class rotateTest : MonoBehaviour {
    private void Start()
    {
        Debug.DrawLine(transform.position, transform.position + Vector3.up, Color.cyan,1000);
        Debug.DrawLine(transform.position, transform.position + transform.forward, Color.black,1000);
        Vector3 cross = Vector3.Cross(Vector3.up, transform.forward);
        Debug.DrawLine(transform.position, transform.position + cross, Color.white, 1000);
        transform.rotation = Quaternion.FromToRotation(Vector3.up, transform.forward);
    }
}
Inverse:返回旋转的逆
函数定义:
public static Quaternion Inverse(Quaternion rotation)
代码示例:
using UnityEngine;

public class rotateTest : MonoBehaviour
{
    private void Update()
    {
        //绕世界坐标轴Y轴顺时针旋转90度
        Quaternion q = new Quaternion(0, 0.525f, 0, 0.525f);
        //绕世界坐标轴Y轴逆时针旋转90度
        transform.rotation = Quaternion.Inverse(q);
        Debug.Log(q + ":" + Quaternion.Inverse(q) + ":" + Quaternion.Inverse(q).normalized + ":" + transform.rotation);
    }
}
//由于四元数:q = [cos(θ/2) (sin(θ/2)n(x) sin(θ/2)n(y) sin(θ/2)n(z))] = [w (x y z)]
//四元数q的逆:表示沿q的相反方向旋转相同的角度 = [w (-x -y -z)]或表示沿q的方向旋转负的旋转角=[-w (x y z)]
//注意是与归一化后的值相等
输出结果:(0.0, 1.0, 0.0, 1.0):(0.0, -1.0, 0.0, 1.0):(0.0, -0.7, 0.0, 0.7):(0.0, -0.7, 0.0, 0.7)
Lerp:在a和b之间用t插值,然后将结果归一化。将参数t固定到范围[0,1].运算效率比Slerp快,但如果旋转相距很远,看起来效果则不太好。
函数定义:public static Quaternion Lerp(Quaternion a,Quaternion b,float t);
using UnityEngine;

public class rotateTest : MonoBehaviour {
    private void Update()
    {
        Quaternion Q1 = new Quaternion(0, 0.525f, 0, 0.525f);
        Quaternion Q2 = new Quaternion(0.525f, 0, 0, 0.525f);
        Debug.DrawLine(transform.position, transform.position + Vector3.up, Color.green);
        Debug.DrawLine(transform.position, transform.position + Vector3.right, Color.red);
        //从transform绕世界坐标轴Y轴旋转90度时的位置,Lerp到transform绕世界坐标轴X轴旋转90度的位置
        //即从transform.rotaion = Q1 到 transform.rotation = Q2
        transform.rotation = Quaternion.Lerp(Q1, Q2, Time.time * 0.1f);
    }
}
LerpUnclamped:在a和b之间用t插值,然后将结果归一化。参数t不需要固定范围.a和b之间用t插值,然后将结果归一化。参数t没有被限制在[0,1]之间。这比Slerp快,但如果旋转相距很远,则看起来效果不太好。
函数定义:
public static Quaternion LerpUnclamped(Quaternion a,Quaternion b,float);
LookRotation:创建具有指定的向前和向上方向的旋转。Z轴将对其forward方向,X轴与forward和upwards的叉积对其,Y轴与Z轴和X轴的叉积对齐。返回identity如果forward或者upward的长度为0,返回identity如果forward和upwards共线。
函数定义:public static Quaternion LookRotation(Vector3 forward,Vector3 upwards = Vector3.up);
函数参数:
1.forward:朝向的方向
2.upwards:定义方向up
代码示例:
using UnityEngine;

public class rotateTest : MonoBehaviour
{
    public Transform target;
    private void Update()
    {
        Vector3 relativePos = target.position - transform.position;
        Quaternion rotation = Quaternion.LookRotation(relativePos, Vector3.up);
        transform.rotation = rotation;
    }
}
Normalize:将这个四元数转换为方向相同但模为1的四元数。归一化时,四元数保持相同的方向,但其模为1。注意,此方法会改变当前的四元数,如果要保持当前四元数不变,请改用normalized属性。如果此四元数太小而无法规范化,则将其设置为Quaternion.identity.
函数定义:public static Quaternion Normalize(Quaternion q);
代码示例:
using UnityEngine;

public class rotateTest : MonoBehaviour
{
    private void Start()
    {
        Quaternion q = new Quaternion(0, 0.525f, 0, 0.525f);
        Debug.Log(q + ":" + q.normalized + ":" + q + ":" + Quaternion.Normalize(q) + ":" +q);
    }
}
输出结果:(0.0, 0.5, 0.0, 0.5):(0.0, 0.7, 0.0, 0.7):(0.0, 0.5, 0.0, 0.5):(0.0, 0.7, 0.0, 0.7):(0.0, 0.5, 0.0, 0.5)
RotateTowards:从from旋转到to.from四元数通过maxDegreesDelta的角度步长向前旋转(注意:旋转不会超过to的值)。负的maxDegreesDelta将远离to方向,直到旋转到完全相反的方向。
函数定义:public static Quaternion RotateTowards(Quaternion from,Quaternion to,float maxDegreesDelta);
代码示例:
using UnityEngine;

public class rotateTest : MonoBehaviour
{
    public Transform target;
    public float speed;
    private void Update()
    {
        var step = speed * Time.deltaTime;
        transform.rotation = Quaternion.RotateTowards(transform.rotation, target.rotation, step);
    }
}
Slerp:在a和b之间用t进行球面插值,将参数t固定在范围[0,1]
函数定义:public static Quaternion Slerp(Quaternion a,Quaternion b,float t)
using UnityEngine;

public class rotateTest : MonoBehaviour
{
    public Transform from;
    public Transform to;
    private float timeCount = 0.0f;
    private void Update()
    {
        transform.rotation = Quaternion.Slerp(from.rotation, to.rotation, timeCount);
        timeCount = timeCount + Time.deltaTime;
    }
}
SlerpUnClamped:在a和b之间用t进行球面插值,参数t不需要固定范围
函数定义:public static Quaternion SlerpUnclamped(Quaternion a,Quaternion b,float t);

Operators

operator *:第一个函数表示:结合旋转lhs和rhs。通过乘积与lhs*rhs旋转与按顺序应用两个旋转相同:先是lhs,然后在进行lhs旋转后的坐标系下进行rhs旋转。请注意,这意味着旋转时不可交换的,因此lhs * rhs不等于 rhs * lhs。第二个函数表示:根据rotation旋转point.
函数定义:
1.public static Quaternion operator*(Quaternion lhs,Quaternion rhs);
2.public static Vector3 operator*(Quaternion rotation,Vector3 point);
函数参数:
1.lhs:左边的四元数
2.rhs:右边的四元数
代码示例1:
using UnityEngine;

public class rotateTest : MonoBehaviour
{
    public Transform extraRotation;
    void Update()
    {
        transform.rotation *= extraRotation.rotation;
    }
}
代码示例2:
using UnityEngine;

public class rotateTest : MonoBehaviour
{
    public Vector3 relativeDirection = Vector3.forward;
    private void Update()
    {
        Debug.DrawLine(Vector3.zero, Vector3.zero + relativeDirection, Color.red);
        Vector3 absoluteDirection = transform.rotation * relativeDirection;
        Debug.DrawLine(Vector3.zero, Vector3.zero + absoluteDirection, Color.yellow);
        transform.position += absoluteDirection * Time.deltaTime;
    }
}
operator ==:判断两个四元数是否相等.这个函数测试两个四元数的点积是否接近1.0.注意,因为四元数可以表示最多连个完整旋转(720)的旋转,所以即使结果旋转看起来相同,此比较也可能返回false.
函数定义:public static bool operator==(Quaternion lhs,Quaternion rhs);

物体A存在以下关系:

A.transform.up = A.transform.rotation * Vector3.up;
A.transform.right = A.transform.rotation * Vector3.right;
A.transform.forward = A.transform.rotation * Vector3.forward;
//transform.forward向量旋转至mouseWorldPos向量
Quaternion lookAtRotate = Quaternion.FromToRotation(A.transform.forward, mouseWorldPos);
//下面两句是等价的:transform.forward向量旋转至mouseWorldPos关于transform.up对称的向量
lookAtRotate = new Quaternion(-lookAtRotate.x, -lookAtRotate.y, -lookAtRotate.z, lookAtRotate.w);
lookAtRotate = new Quaternion(lookAtRotate.x, lookAtRotate.y, lookAtRotate.z, -lookAtRotate.w);
Quaternion origin = A.rotation;
A.rotation = lookAtRotate,此时
A.transform.forward = lookAtRotate * (Quaternion origin * Vector3.forward);
Quaternion quat = Quaternion.AngleAxis(Time.time * 180,A.transform.forward);
A.rotation = quat
此时:
A.transform.up = quat * Vector3.up,也就是Vector3.up绕A.transform.forward旋转Time.time * 180
若换成:
A.rotation = quat * A.rotation,也就是Vector3.up旋转到当前A的位置,然后绕A.transform.forward旋转Time.time * 180
A.rotation = A.parent.rotation * A.localRotation

Unity旋转顺序:

using UnityEngine;

public class RotateTest : MonoBehaviour
{
    public Transform target1;
    public Transform target2;
    public Transform target3;
    void Start()
    {
        //Transform.Rotate的实现
        // public void Rotate(Vector3 eulers, [UnityEngine.Internal.DefaultValue("Space.Self")] Space relativeTo)
        //{
        //    Quaternion eulerRot = Quaternion.Euler(eulers.x, eulers.y, eulers.z);
        //    if (relativeTo == Space.Self)
        //        localRotation = localRotation * eulerRot;
        //    else
        //    {
        //        rotation = rotation * (Quaternion.Inverse(rotation) * eulerRot * rotation);
        //    }
        //}
        //以下三种方式所得结果一致
        //    target1.Rotate(new Vector3(30, 40, 50), Space.World);
        //    target2.Rotate(new Vector3(0, 0, 50), Space.World);
        //    target2.Rotate(new Vector3(30, 0, 0), Space.World);
        //    target2.Rotate(new Vector3(0, 40, 0), Space.World);
        //    Quaternion x = Quaternion.AngleAxis(30, Vector3.right);
        //    Quaternion y = Quaternion.AngleAxis(40, Vector3.up);
        //    Quaternion z = Quaternion.AngleAxis(50, Vector3.forward);
        //    target3.rotation = y * x * z;
    //以下三种方式所得结果一致
    target1.Rotate(new Vector3(30, 40, 50), Space.Self);
        target2.Rotate(new Vector3(0, 40, 0), Space.Self);
        target2.Rotate(new Vector3(30, 0, 0), Space.Self);
        target2.Rotate(new Vector3(0, 0, 50), Space.Self);
        Quaternion x = Quaternion.AngleAxis(30, Vector3.right);
        Quaternion y = Quaternion.AngleAxis(40, Vector3.up);
        Quaternion z = Quaternion.AngleAxis(50, Vector3.forward);
        target3.rotation = y * x * z;
    }
}

参考资料:
1.https://docs.unity3d.com/ScriptReference/Quaternion.html
2.https://github.com/Unity-Technologies/UnityCsReference/blob/master/Runtime/Export/Quaternion.cs
3.https://github.com/Unity-Technologies/UnityCsReference/blob/master/Runtime/Export/Vector3.cs
4.【重要:必看】【复数与四元数】https://krasjet.github.io/quaternion/quaternion.pdf
5.【正交投影矩阵】https://zhuanlan.zhihu.com/p/28379857
6.【Transform】https://github.com/Unity-Technologies/UnityCsReference/tree/master/Runtime/Transform/ScriptBindings

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值