在Unity3D中使用lerp时,如何使相机在不同位置之间暂时停顿?

时间:2018-10-13 04:25:14

标签: c# unity3d camera coroutine lerp

我有一系列位置,我希望相机在它们之间移动/固定。有两个按钮(按钮A和按钮B)触发相机移动位置。如果用户按下按钮A,则摄像机将束紧到阵列中的上一个位置。如果用户按下按钮B,则摄像机将跳至阵列中的下一个位置。但是,在移动到新位置之前,我希望照相机将镜头拉到中间位置,在那里暂停几秒钟,然后再移动。这是我目前所拥有的伪代码:

 void Update() 
     {
         if (buttonPress == a) {
             positionToMoveTo = positions[currentPosition--];
         } 
         if (buttonpress == b) {
             positionToMoveTo = positions[currentPosition++];
         }
     }

 void LateUpdate() 
    {
         camera.lerp(intermediatePosition);
         StartCoroutine(pause());
    } 

 IEnumerator pause() 
    {
         yield return new WaitForSeconds(3f);
         camera.lerp(positionToMoveTo);
    }

但这不起作用,因为切换摄像机位置时出现奇怪的抖动,并且中间位置并非总是发生。我认为我的问题与执行顺序有关,但我无法弄清楚。任何帮助都会很棒:)

1 个答案:

答案 0 :(得分:0)

由于LateUpdate在所有Update调用完成后每帧都运行一次,因此您将开始新的协程帧!

您可以通过稍微不同的方法来避免这种情况:

private bool isIntermediate;
private bool moveCamera;

private void LateUpdate ()
{
    if(!moveCamera) return;

    if(isIntermediate)
    {
        camera.lerp(intermediatePosition);
    } 
    else 
    {
        camera.lerp(positionToMoveTo);
    }     
}

private IEnumerator MoveCamera() 
{
    moveCamera = true;
    isIntermediate=true;
    yield return new WaitForSeconds(3f);
    isIntermediate=false;

    // Wait until the camera reaches the target
    while(camera.transform.position == PositionToMoveTo){
        yield return null;
    }

    // Stop moving
    moveCamera = false;

    // just to be sure your camera has exact the correct position in the end
    camera.transform.position = PositionToMoveTo;
}

或者,您也可以在没有LateUpdate的情况下在协程中进行所有移动(但老实说,我不确定协程是否在Update之前或之后完成)

private IEnumerator MoveCamera() 
{
    float timer = 3f;
    while(timer>0)
    {
       timer -= Time.deltaTime;
       camera.lerp(intermediatePosition);
       yield return null;
    }

    // Wait until the camera reaches the target
    while(camera.transform.position == PositionToMoveTo){
        camera.lerp(PositionToMoveTo);
        yield return null;
    }

    // just to be sure your camera has exact the correct position in the end
    camera.transform.position = PositionToMoveTo;
}

第二个会更干净,因为我不知道您是否需要在LateUpdate中运行它


注意:Vector3的==运算符的精度为0.00001。如果您需要更高或更小的精度,则必须更改为

if(Vector3.Distance(camera.transform.position, PositionToMoveTo) <= YOUR_DESIRED_THRESHOLD)

现在您要做的就是每次要更改相机位置时都呼叫协程。

void Update() 
 {
     if (buttonPress == a) 
     {
         // Make sure the Coroutine only is running once
         StopCoroutine(MoveCamera);
         positionToMoveTo = positions[currentPosition--];
         StartCoroutine (MoveCamera);
     } 
     if (buttonpress == b) 
     {
         // Make sure the Coroutine only is running once
         StopCoroutine (MoveCamera);
         positionToMoveTo = positions[currentPosition++];
         StartCoroutine (MoveCamera);
     }
 }