簡體   English   中英

四元數來回

[英]Quaternion lerp back and forth

我想lerp沿Z軸來回等量避免紡(如我的sprite是不是圓形的)。 為此,我計划將forward angle隨機化,將其存儲起來, lerp它,然后lerp相同的角度。 但是,這會產生一些怪異的彈出聲,因為向后旋轉開始時的起始角度將不相同,而是相同。 當我調用它時,我給它同時進行插值的時間。 一些代碼:

IEnumerator LerpQuat(QuatLerpInput rotThis, float time, float leftBoundary, float rightBoundary)
{
    /*
     * we want to rotate forward, then backward the same amount
     * to avoid spinning. we store the given value to both of these.
    */

    Transform stuffToRot = rotThis.godRayGO.transform;

    float lastTime = Time.realtimeSinceStartup;
    float timer = 0.0f;
    switch (rotThis.rotState)
    {
        case (QuatLerpInput.RotationStates.rotAway):
            rotThis.deltaRot = Random.Range(leftBoundary, rightBoundary);
            while (timer < time)
            {
                stuffToRot.rotation = Quaternion.Euler(stuffToRot.rotation.x, stuffToRot.rotation.y,
                    Mathf.LerpAngle(rotThis.idleRot, rotThis.idleRot + rotThis.deltaRot, timer / time));
                timer += (Time.realtimeSinceStartup - lastTime);
                lastTime = Time.realtimeSinceStartup;
                yield return null;
            }
            rotThis.rotState = QuatLerpInput.RotationStates.setBack;
            break;
        case (QuatLerpInput.RotationStates.setBack):
            while (timer < time)
            {
                stuffToRot.rotation = Quaternion.Euler(stuffToRot.rotation.x, stuffToRot.rotation.y,
                    Mathf.LerpAngle(rotThis.idleRot + rotThis.deltaRot, rotThis.idleRot, timer / time));
                timer += (Time.realtimeSinceStartup - lastTime);
                lastTime = Time.realtimeSinceStartup;
                yield return null;
            }
            rotThis.rotState = QuatLerpInput.RotationStates.rotAway;
            break;
    }

}
public class QuatLerpInput
{
    public GameObject godRayGO;
    public float deltaRot;
    public float idleRot;
    public enum RotationStates
    {
        rotAway, setBack
    }
    public RotationStates rotState = RotationStates.rotAway;
    public QuatLerpInput(GameObject godRayGO)
    {
        this.godRayGO = godRayGO;
        deltaRot = godRayGO.transform.rotation.z;
        idleRot = godRayGO.transform.rotation.z;
    }
}

使用四元數編輯的switch

switch (rotThis.rotState)
    {
        case (QuatLerpInput.RotationStates.rotAway):
            rotThis.deltaRot = Random.Range(leftBoundary, rightBoundary);
            Quaternion destination = new Quaternion(rotThis.idleQuat.x, rotThis.idleQuat.y, rotThis.idleQuat.z + rotThis.deltaRot, 1.0f);
            rotThis.deltaQuat = destination;
            while (timer < time)
            {
                stuffToRot.rotation = Quaternion.Slerp(rotThis.idleQuat, rotThis.deltaQuat, timer/time);
                //stuffToRot.rotation = Quaternion.Euler(stuffToRot.rotation.x, stuffToRot.rotation.y,
                //    Mathf.LerpAngle(rotThis.idleRot, rotThis.idleRot + rotThis.deltaRot, timer / time));
                timer += (Time.realtimeSinceStartup - lastTime);
                lastTime = Time.realtimeSinceStartup;

                yield return null;
            }
            rotThis.rotState = QuatLerpInput.RotationStates.setBack;
            break;
        case (QuatLerpInput.RotationStates.setBack):
            while (timer < time)
            {
                stuffToRot.rotation = Quaternion.Slerp(rotThis.deltaQuat, rotThis.idleQuat, timer / time);
                //stuffToRot.rotation = Quaternion.Euler(stuffToRot.rotation.x, stuffToRot.rotation.y,
                //    Mathf.LerpAngle(rotThis.idleRot + rotThis.deltaRot, rotThis.idleRot, timer / time));
                timer += (Time.realtimeSinceStartup - lastTime);
                lastTime = Time.realtimeSinceStartup;

                yield return null;
            }
            rotThis.rotState = QuatLerpInput.RotationStates.rotAway;
            break;
    }

而不是約束角度,您應該計算目標四元數並使用Quaternion.Slerp插值到隨機四元數並返回。

對於任何看到這一點的人,我都找到了解決方案。

void LerpQuat(QuatLerpInput rotThis, float time, float leftBoundary, float rightBoundary)
{
    /*
     * we want to rotate forward, then backward the same amount
     * to avoid spinning. we store the given value to both of these.
    */

    Transform stuffToRot = rotThis.godRayGO.transform;

    float lastTime = Time.realtimeSinceStartup;
    float timer = 0.0f;

    switch (rotThis.rotState)
    {
        case (QuatLerpInput.RotationStates.rotAway):
            rotThis.deltaRot = Random.Range(leftBoundary, rightBoundary);
            Quaternion destination = new Quaternion(rotThis.idleQuat.x, rotThis.idleQuat.y, rotThis.deltaRot, 1.0f);
            rotThis.deltaQuat = destination;
            rotThis.deltaEulerAngle = Vector3.forward * rotThis.deltaRot;               
            StartCoroutine(RotateMe(rotThis, rotThis.idleQuat, rotThis.deltaEulerAngle, initiateAlphaSwap));
            break;
        case (QuatLerpInput.RotationStates.setBack):
            StartCoroutine(RotateMe(rotThis, rotThis.deltaQuat,-1.0f * rotThis.deltaEulerAngle, initiateAlphaSwap));
            break;
    }
}
IEnumerator RotateMe(QuatLerpInput whatToRotate,Quaternion fromWhere,Vector3 byAngles, float inTime)
{
    Quaternion fromAngle = fromWhere;
    Quaternion toAngle = Quaternion.Euler(whatToRotate.godRayGO.transform.eulerAngles + byAngles);
    toAngle = new Quaternion(toAngle.x, toAngle.y, toAngle.z, 1.0f);

    if(whatToRotate.rotState == QuatLerpInput.RotationStates.setBack)
    {
        fromAngle = new Quaternion(whatToRotate.RotEndPos.x, whatToRotate.RotEndPos.y, whatToRotate.RotEndPos.z, 1.0f);
        toAngle = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
    }

    for (float t = 0.0f; t < 1.0f; t += Time.deltaTime / inTime)
    {
        whatToRotate.godRayGO.transform.rotation = Quaternion.Lerp(fromAngle, toAngle, t);
        yield return null;
    }
    if(whatToRotate.rotState == QuatLerpInput.RotationStates.rotAway)
    {
        whatToRotate.rotState = QuatLerpInput.RotationStates.setBack;
        whatToRotate.RotEndPos = new Vector3(toAngle.x, toAngle.y, toAngle.z);
    }
    else
    {
        whatToRotate.rotState = QuatLerpInput.RotationStates.rotAway;
    }

}

解決方法是在loop連續使用Quaternion.Lerp在循環結束后設置狀態。 這樣就可以實現我想要的功能。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM