欧拉角

什么是欧拉角

用三个数去存储物体在x、y、z轴的旋转角度。

补充:

  • 为了避免万向节死锁,y和z轴取值范围都是0~360°,x轴是-90°~90°。

  • x和z轴是旋转是相对于自身坐标轴的,y轴旋转永远是相对于世界坐标轴的。

    优点

  • 好理解,使用方便

  • 只用三个数表示,占用空间少,在表示方位的数据结构中是占用最少的

    缺点

  • 万向节死锁

    四元数

    什么是四元数

  • Quaternion在3D图形学中表示旋转,由一个三维向量(X/Y/Z)和一个标量(W)组成。

  • 旋转轴为V,旋转弧度为θ,如果使用四元数表示,则四个分量为:

    • x = sin(θ/2)*V.x
    • y = sin(θ/2)*V.y
    • z = sin(θ/2)*V.z
    • w = cos(θ/2)
  • X、Y、Z、W的取值范围是-1~1。

  • API:Quaternion qt = this.transform.rotation;

    四元数的运算

优点

  • 避免万向节死锁
    • 可使物体沿自身坐标Y轴旋转
      this.transform.rotation *= Quaternion.Euler(0,1,0);
    • rotate内部就是使用四元数相乘实现
      this.transform.Rotate(Vector3 eulerAngles)

      缺点

  • 难于使用,不建议单独修改某个数值。
  • 存在不合法的四元数。

实例

使用欧拉角旋转

代码如下:

public class EulerDemo : MonoBehaviour
{
    public Vector3 euler;
    void Update()
    {
        euler = this.transform.eulerAngles;
    }
    private void OnGUI()
    {
        if (GUILayout.RepeatButton("沿x轴旋转"))
        {
            this.transform.eulerAngles += Vector3.right;
        }
        if (GUILayout.RepeatButton("沿y轴旋转"))
        {
            this.transform.eulerAngles += Vector3.up;
        }
        if (GUILayout.RepeatButton("沿z轴旋转"))
        {
            this.transform.eulerAngles += Vector3.forward;
        }
    }

}

使用四元数旋转

代码如下:

public class QuaternionDemo : MonoBehaviour
{
    public Vector3 euler;
    void Update()
    {
        euler = this.transform.eulerAngles;
    }
    private void OnGUI()
    {
        if (GUILayout.RepeatButton("沿x轴旋转"))
        {
            /*
             //方法一
             Quaternion qt = new Quaternion();
            //旋转轴
            Vector3 axis = this.transform.right;
            //旋转角度
            float rad = 1 * Mathf.Deg2Rad;
            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);
            this.transform.rotation = qt;

            //方法二
            this.transform.rotation *= Quaternion.Euler(Vector3.right);

            //方法三
            this.transform.Rotate(Vector3.right);
            */

            this.transform.Rotate(Vector3.right);
        }
        if (GUILayout.RepeatButton("沿y轴旋转"))
        {
            this.transform.Rotate(Vector3.up);
        }
        if (GUILayout.RepeatButton("沿z轴旋转"))
        {
            this.transform.Rotate(Vector3.forward);
        }
    }
}
最后修改:2020 年 11 月 30 日
如果觉得我的文章对你有用,请随意赞赏