Unity - 四元数常用方法

621 阅读2分钟

插值运算

与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
  1. 先快后满
//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°,第三颗,第四颗……后面就是一样的逻辑了。

qrcode.jpg