文章目录
- 简介
- Quaternion类属性
- 静态属性
- 属性
- 构造函数
- 方法
- 静态方法
- 运算符
- 欧拉角
简介
Quaternion又称四元数,由x,y,z和w这四个分量组成,是由爱尔兰数学家威廉·卢云·哈密顿在1843年发现的数学概念。四元数的乘法不符合交换律。从明确地角度而言,四元数是复数的不可交换延伸。如把四元数的集合考虑成多维实数空间的话,四元数就代表着一个四维空间,相对于复数为二维空间。
四元数不存在欧拉角的万向锁问题,旋转大小角问题,以及旋转不唯一(同一个旋转结果,可以有多个旋转顺序及角度定义)问题,用起来简单。
在Unity中,用Quaternion来存储和表示对象的旋转角度。Quaternion的变换比较复杂,对于GameObject一般的旋转及移动,可以用Transform中的相关方法实现。
最常用的功能为:Quaternion.LookRotation, Quaternion.Angle, Quaternion.Euler, Quaternion.Slerp, Quaternion.FromToRotation, Quaternion.identity
Quaternion类属性
静态属性
属性
- eulerAngles
- normalized
- x,y,z 旋转轴,不建议直接修改该值。
- w 转转角度,不可以直接修改该值。
构造函数
- Quaternion
public Quaternion(float x, float y, float z, float w);
构造一个四元数。
方法
- Set
public void Set(float newX, float newY, float newZ, float newW);
修改四元数。 - SetFromToRotation
public void SetFromToRotation(Vector3 fromDirection, Vector3 toDirection);
构建一个从fromDirectoion到toDirection的旋转。 - SetLookRotation
public void SetLookRotation(Vector3 view, Vector3 up = Vector3.up);
view:观察方向
up:定义向上的方向
用向上和向前的方向构建旋转。
如果用来确定Transform的朝向,则Z轴是forward,Y轴是upwards。如果forward的方向(view)是0,会报错。 - ToAngleAxis
public void ToAngleAxis(out float angle, out Vector3 axis);
将旋转,转换成轴角对。这里角是角度。
静态方法
- Angle
public static float Angle(Quaternion a, Quaternion b);
计算两个旋转之间的角度。 - AngleAxis
public static Quaternion AngleAxis(float angle, Vector3 axis);
创建一个围绕 axis 轴旋转 angle 度的旋转。 - Dot
public static float Dot(Quaternion a, Quaternion b);
计算两个旋转的点积。目前使用场景不详。
点积也叫做欧几里得内积,四元数的点积等同于一个四维矢量的点积。点积的值是p中每个元素的数值与q中相应元素的数值的乘积的和。 - Euler
public static Quaternion Euler(float x, float y, float z);
根据欧拉角生成四元数。旋转顺序按照z->y->z。 - FromToRotation
public static Quaternion FromToRotation(Vector3 fromDirection, Vector3 toDirection);
构建从fromDirection到toDirection的旋转。
通常用来旋转 transform 来保证其一个轴朝向世界空间中的toDirection。例如:
设置对象的Y轴朝向z轴(绕x轴旋转90度)
transform.rotation = Quaternion.FromToRotation(Vector3.up, transform.forward); - Inverse
public static Quaternion Inverse(Quaternion rotation);
反向旋转。数学实现时,可以是旋转轴取反,也可以是w值取反。
测试Unity是对旋转轴取反来实现的。 - Lerp
public static Quaternion Lerp(Quaternion a, Quaternion b, float t);
在2个旋转之间进行线性插值。
该旋转要比Slerp快,但是当两个旋转差别比较大时,效果不好。
如果是渐进式的更新旋转,确定两个旋转差别比较小时,可以用这个来提升效率。 - LerpUnclamped
public static Quaternion LerpUnclamped(Quaternion a, Quaternion b, float t);
功能同上,只是,允许t<0或t>1 - Slerp
public static Quaternion Slerp(Quaternion a, Quaternion b, float t);
在两个旋转之间进行球面插值。0<=t<=1 - SlerpUnclamped
public static Quaternion SlerpUnclamped(Quaternion a, Quaternion b, float t);
功能同上,允许t<0或t>1 - LookRotation
public static Quaternion LookRotation(Vector3 forward, Vector3 upwards = Vector3.up);
根据forward和upwards的方向,创建旋转。
该旋转的Z轴对齐forward,X轴对齐forward和upwards的叉积向量,Y轴对齐Z和X轴的叉积。 - Normalize
public static Quaternion Normalize(Quaternion q);
将四元数转成方向不变,但是四元数长度为1的四元数(模)。
该方法会改变参数四元数。 - RotateTowards
public static Quaternion RotateTowards(Quaternion from, Quaternion to, float maxDegreesDelta);
旋转四元数(比如旋转朝向)。当旋转角度大于maxDegreesDelta,仅旋转maxDegreesDelta。比如,保持跟另一个对象朝向一致:
transform.rotation = Quaternion.RotationTowards(transform.rotation,target.rotation,rotSpeed*Time.deltaTime);
运算符
- operator *
public static Quaternion operator *(Quaternion lhs, Quaternion rhs);
组合2个旋转。可以认为旋转效果相加:
transform.rotation = Quaternion.AngleAxis(rotSpeedTime.deltaTime, Vector3.up);
欧拉角
欧拉角,用分别三个轴上的旋转,来表示一个完整的3D空间的旋转,Unity以Z->X->Y轴的顺序依次执行旋转,该顺序非常重要,因为同样的旋转,不同的顺序,结果是不同的。