0
\$\begingroup\$

I have asked this question on other community but still get no response after a month, so I decided to ask it here.

I am trying to put player position to the middle of camera when it is reaching near the edge of the camera. It works correctly with the following code:

transform.position = playerPosition;

where playerPosition is the current position of the player.

But, when I try it with Vector3.Lerp or Vector3.MoveTowards, it won't reach the player's x position.

Here is how it looks when using Lerp or MoveTowards

https://www.youtube.com/watch?v=E50RpycrUxI

And here is when not using Lerp or MoveTowards

https://www.youtube.com/watch?v=ng_A4AfDQFE

The script:

 public GameObject player;
 private Vector3 playerPosition;
 private Vector3 pos;
 public float offsetSmoothness;
 void Update () {
     // player's position relative to camera
     pos = Camera.main.WorldToViewportPoint(player.transform.position);
     playerPosition = new Vector3(player.transform.position.x,
                                    transform.position.y,
                                    transform.position.z);
     // if player reach the edge of the camera do the following
     if (pos.x < 0.1 || pos.x > 0.9)
     {
          transform.position = Vector3.Lerp (transform.position,
                                                playerPosition,
                                                offsetSmoothness * Time.deltaTime);
          // transform.position = playerPosition;
     }
 }

Why Vector3.Lerp is not positioning the player to the center of the camera when this condition is used to execute it: if (pos.x < 0.1 || pos.x > 0.9) ?

And how to make it working as expected, which is making the Vector.Lerp position the player to the center of camera when the player close to the edge of the camera?

\$\endgroup\$
  • \$\begingroup\$ How much is offsetSmoothness? \$\endgroup\$ – Bálint Feb 7 '18 at 23:29
  • \$\begingroup\$ @Bálint offsetSmoothness is dynamic variable. It has no effect other than making the camera movement slower or faster. I set it to 10 on the Inspector panel. \$\endgroup\$ – KeepMove Feb 8 '18 at 2:28
  • \$\begingroup\$ Lerp accepts values between 0 and 1 and the less it is, the smoother the result will be. You should probably look up what it actually does. \$\endgroup\$ – Bálint Feb 8 '18 at 5:53
  • \$\begingroup\$ @Bálint I have no problem with smoothness. I want to center the player inside the camera once it is reaching the edge of the camera. \$\endgroup\$ – KeepMove Feb 8 '18 at 10:21
2
\$\begingroup\$

This is because you are only calling Vector3.Lerp or MoveTowards while pos.x < 0.1 || pos.x > 0.9. This means that once the camera moves a little bit pos.x < 0.1 || pos.x > 0.9 won't be true anymore so the camera won't keep moving. To fix this you could create a co-routine that runs until the player is in the middle of the camera:

public GameObject player;
public float speed;
private bool isMovingCamera;

void Update () {
    // player's position relative to camera
    Vector3 pos = Camera.main.WorldToViewportPoint(player.transform.position);
    Vector3 playerPosition = new Vector3(player.transform.position.x,
                                    transform.position.y,
                                    transform.position.z);
    // if player reach the edge of the camera do the following
    if ((pos.x < 0.1 || pos.x > 0.9) && !isMovingCamera)
    {
        StartCoroutine(CenterCameraOnPlayer());
    }
}

IEnumerator CenterCameraOnPlayer() {
    isMovingCamera = true;

    do {
        Vector3 camPos = transform.position;
        Vector3 playerPos = player.transform.position;


        float step = speed * Time.deltaTime;
        // Move camera towards player at speed units per second.
        transform.position = Vector3.MoveTowards(camPos, playerPos, step);
        yield return null;
    } while(Vector3.Distance(camPos, playerPos) > 0.1f);

    isMovingCamera = false;
}

You might have to tweak some numbers (like 0.1f in the while condition) to make it feel right. This is also untested, but the general idea should work.

\$\endgroup\$
0
\$\begingroup\$

You're misunderstanding Lerp, or Linear Interpolation. You're not supposed to set the third parameter or t to speed * time, you're supposed to give it a value between 0-1 for which it will interpolate.

So:

Lerp(A, B, 1) will return B,

Lerp(A, B, 0) will return A,

Lerp(A, B, 0.5) will return the middle point between A and B.

With that in mind, what you need is to have a function that makes t go from 0-1 within X seconds.

\$\endgroup\$
  • \$\begingroup\$ There are actually two common patterns for using lerp, and they can involve time in the third parameter. See a deeper write-up in this answer. \$\endgroup\$ – DMGregory Mar 11 '18 at 19:32
  • \$\begingroup\$ It is just the way to use what is exist. \$\endgroup\$ – KeepMove Mar 11 '18 at 22:28
  • \$\begingroup\$ @DMGregory thanks for the link, interesting read. Although it is a valid way to use it, i feel like many people use Lerp like that [using time for t] without knowing what linear interpolation really is, so i just wanted to clear that up. \$\endgroup\$ – NoobStudios Mar 12 '18 at 21:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.