0

I have an array of positions that I want my camera to move/lerp between. There are two buttons (button A and button B) that trigger the camera to move position. If the user presses button A, the camera will lerp to the previous position in the array. If the user presses button B, the camera will lerp to the next position in the array. However, before moving to a new position, I want the camera to lerp to an intermediate position, pause there for a couple of seconds, and then move. Here is the pseudocode for what I have at the moment:

 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);
    }

This doesn't work though because I get strange jittering when switching camera positions and my intermediate position doesn't always occur. I think my problem has something to do with execution order but I can't figure it out. Any help would be great :)

BobSacamano
  • 157
  • 1
  • 8
  • What exactly is `camera` and `camera.lerp`? And what does `buttonpress == a`? – derHugo Oct 13 '18 at 05:10
  • "buttonpress == a" and "buttonpress == b" checks if the button pressed was Button A or Button B. camera.lerp moves the camera into the position given using interpolation – BobSacamano Oct 13 '18 at 05:22
  • Please add the code for those. E.g. I can't see if camera is a transform or another class. – derHugo Oct 13 '18 at 05:44
  • The camera is a transform. The button checks use another class to check for which step in the game the user is in. Adding the actual code may overcomplicate things. The code above is attached to the camera – BobSacamano Oct 13 '18 at 05:51

1 Answers1

0

You start a new Coroutine every frame since LateUpdate runs every frame after all Update calls are finished!

You could avoid this by a slightly different approach:

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;
}

Alternatively you could do all the movement in the Coroutine without LateUpdate (but honestly I'm not sure if the Coroutines are done before or after 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;
}

This second one would be cleaner bjt as said I don't know if it is a requirement for you to have it run in LateUpdate


Note: the == operator of Vector3 has a precision of 0.00001. If you need a better or weaker precision you have to change to

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

Now all you have to do is to call your Coroutine Everytime you want to change the camera position.

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);
     }
 }
derHugo
  • 83,094
  • 9
  • 75
  • 115
  • I hope it helps you to find the problems in your code. I hacked this in on my smartphone so I cannot guarantee currently that there are no syntax or spelling errors. – derHugo Oct 13 '18 at 06:03
  • Ohhhhh, I understand now. Thanks for your help derHugo! You've cleared it up for me. – BobSacamano Oct 13 '18 at 15:56