当用户停止旋转船时,如何使其平稳地向后旋转?

时间:2019-02-01 15:30:11

标签: c# unity3d

所以这个问题可能还不清楚,但是船可以用箭头键完美地旋转,但是当释放箭头键时,我希望它旋转回到位置(0,yRotation,0),但要平滑运动(用户首先旋转的动作相同),知道我该怎么做吗?

xRotation,yRotation和zRotation都初始化为0。

    float xThrow = CrossPlatformInputManager.GetAxis("Horizontal");


        if(xThrow > 0) {

            transform.rotation = Quaternion.Euler(xRotation, yRotation +     0.6f, zRotation - 0.6f);
            yRotation += 0.6f;
            zRotation -= 0.6f;
                        }

        else if (xThrow < 0)
        {

            transform.rotation = Quaternion.Euler(xRotation, yRotation -     0.6f, zRotation + 0.6f);
            yRotation -= 0.6f;
            zRotation += 0.6f;
        } 

      else {
            transform.rotation = Quaternion.Euler(0f, yRotation,     zRotation);
            while (zRotation > 0) {
              zRotation -= 0.6f;
            }

            while (zRotation < 0) {
            zRotation += 0.6f;
            }
        }

我编写的代码将其带回到所需的旋转位置,但是它一点都不平滑,只能作为一个框架来执行。我想实现这一目标,但是要以非常平滑的运动,而不是单个框架。

1 个答案:

答案 0 :(得分:0)

假设您想重置else块中的旋转,则应使用Coroutine。注意,因为我也猜想您正在Update方法中使用此方法,所以请小心不要启动多个例程。

// set this in the Inspector
public float resetDuration;

// make sure there is only one routine running at once
private bool isResetting;

// ...

    else 
    {
        // if no routine is running so far start one
        if(!isResetting) StartCoroutine(RotateToIdentity());
    }

// ...

private IEnumerator RotateToIdentity()
{
    isResetting = true;

    // I recommend using this for rotations and not do them by manipulating 
    // 3 float values. Otherwise could also Lerp all three float values and use them for the rotation here as well
    var currentRot = transform.localRotation;
    var targetRot = Quaternion.Identity;

    // than use those
    // var currentX = xRotation;
    // var currentY = yRotation;
    // var currentZ = zRotation;

    var timePassed = 0.0f;
    while(timePassed <= resetDuration)
    {
        // interpolate between the original rotation and the target
        // using timePassed / resetDuration as factor => a value between 0 and 1
        transform.rotation = Quaternion.Lerp(currentRot, targetRot, timePassed / resetDuration);

        // or with your rotations
        // xRotation = Mathf.Lerp(currentX, 0, timePassed / resetDuration);
        // yRotation = Mathf.Lerp(currentY, 0, timePassed / resetDuration);
        // zRotation = Mathf.Lerp(currentZ, 0, timePassed / resetDuration);
        // transform.rotation = Quaternion.Euler(xRotation, yRotation, zRotation);

        // add passed time since last frame
        timePassed += Time.deltaTtime;

        // return to the mein thread, render the frame and go on in the next frame
        yield return null;
    }

    // finally apply the target rotation just to be sure to avoid over/under shooting
    transform.rotation = targetRot;

    // if you really want to go on using xRotation, yRotation and zRotation also reset them when done
    xRotation = 0;
    yRotation = 0;
    zRotation = 0;

    isResetting = false;
}

您还应该考虑将Time.deltaTime用于所有轮换。

使用3个单独的lerps的优势之一:用户再次互动后,他就可以中断重置例程

if(xThrow > 0) 
{   
    StopAllCoroutines();
    isResetting = false;

    // ...
}
else if (xThrow < 0)
{
    StopAllCoroutines();
    isResetting = false;

    // ...
}

// ---