插值运算
与Vector3的插值运算一样,四元数也提供了2种插值运算方法,分别是线性插值Lerp和球形插值Slerp。由于算法不同,对于Vector3来说,Lerp的效果会更好,而对于四元数来说,Slerp的效果会更好。
代码示例
public class Test : MonoBehaviour
{
public Transform A;
public Transform B;
private void Start()
{
}
private void Update()
{
//将A的旋转通过插值到B的旋转
A.rotation = Quaternion.Slerp(A.rotation, B.rotation, Time.deltaTime);
}
}
注意!不管是Lerp还是Slerp,都会有两种方式去实现插值。
//插值公式
result = start + (end-start) *t
- 先快后满
//start = Quaternion.Slerp(start,target,time);
//这种time不变,start每帧变化的插值运算就是先快后满
//(因为start会越来越大,那么end-start 就会越来越小,所以越来越慢),
//而且start只会越来越趋近与target,而不会等于
targetA.rotation = Quaternion.Slerp(A.rotation, B.rotation, Time.deltaTime);
2. 匀速运动
//start 不变,time变化。这种就是匀速运动
public class Test : MonoBehaviour
{
public Transform A;
public Transform B;
//初始旋转
private Quaternion start;
//最终旋转
private Quaternion target;
private float time;
private void Start()
{
}
private void Update()
{
//如果B的旋转不等于最终旋转
if (B.rotation != target)
{
//重置time,start,target
time = 0;
start = A.rotation;
target = B.rotation;
}
//time累加
time += Time.deltaTime;
//插值运算,匀速运动
A.rotation = Quaternion.Slerp(start, target, time);
}
}
四元数相乘
两个四元数相乘会得到一个新的四元数,代表两个旋转量的叠加,相当于旋转了四元数。
注意!旋转相对的坐标系是物体自身的坐标系。即我们之前说到的A.transform.rotation *= Quaternion.AngleAxis(1,Vector3.up); 这里Vector3.up是A物体的Y轴,而不是世界坐标的Y轴。
q3 = q1 * q2
四元数乘向量
四元数乘向量返回一个新的向量,可以将指定的向量旋转对应四元数的旋转量,相当于旋转向量。
注意!必须是四元数在前!即必须是四元数*向量,否则会报错
v2 = q1 * v1
//四元数乘以向量
var v = A.forward;
v = Quaternion.AngleAxis(60, Vector3.up) * v;
print(v);
使用场景
比如发射子弹。初始只能发射1颗,然后吃了个技能就能发射扇形子弹或者环形子弹。那么这个时候就可以用到四元数乘向量了。第一颗子弹是正前方,那么第二颗就是正前方往左或右旋转30°,第三颗,第四颗……后面就是一样的逻辑了。