Как я могу заставить мою камеру временно останавливаться между различными положениями при использовании lerp в Unity3D? - PullRequest
0 голосов
/ 13 октября 2018

У меня есть массив позиций, которые я хочу, чтобы моя камера перемещалась / перемещалась между ними.Есть две кнопки (кнопка 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 голосов
/ 13 октября 2018

Вы запускаете новый Coroutine каждый кадр, так как 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);
     }
 }
...