Using Lerp to move object, isn't stopping at endPos

I have this code to move a object from its existing location to an end position:

startPos = player.gameObject.transform.position;
                endPos = player.gameObject.transform.position + Vector3.forward * distance1;

                currentLerpTime += Time.deltaTime;
                if (currentLerpTime >= lerpTime)
                {
                    currentLerpTime = lerpTime;
                }
                float perc = currentLerpTime / lerpTime;
                player.gameObject.transform.position = Vector3.Lerp(startPos, endPos, perc);

But it isn’t stopping. I tried this added to the bottom of the above with a bool and it still doesn’t stop.

if(Vector3.Distance(startPos, endPos) < 1)
                {
                    startmove = false;
                }

What do I need to do to stop it at the end point?

Is that whole block of code inside Update?
If so, the issue is that you’re recalculating the endPos every time, so it’s always in front of the object.
If not, which code is in what method?

Yes it is in the update. otherwise it doesn’t move.

Doesn’t the distance I entered stop it?

If I put it in a method to call it it only moves a little bit then stops. it doesn’t go to the endPos.

I think it would be helpful to see the complete script. There may be something off about the way this is being called.

But I think your problem is that you set the start and end points relative to player.gameObject.transform, while moving player.gameObject.transform. As the object moves, your start and end points change as well, which will lead to unpredictable behavior. You should store the start and end points before you begin the move and not change them in Update.

The whole code;

public GameObject player;

    private Vector3 startPos;
    private Vector3 endPos;

    private float distance1 = -87f;
    private float distance2 = -76f;
    private float distance3 = -82f;
    private float distance4 = -67f;

    private float lerpTime = 5f;

    private float currentLerpTime = 0f;

    private bool startmove = true;

    public void Start()
    {
        startmove = true;
    }
    public void Update()
    {
        currentLerpTime = 0f;
        Spawn spawnForce = GameObject.Find("Spawn_Points").GetComponent<Spawn>();
        if (startmove == true)
        {
            if (spawnForce.threat_0 == false && spawnForce.threat_1 == true && spawnForce.threat_2 == false && spawnForce.threat_3 == false && spawnForce.threat_4 == false)
            {
                startPos = player.gameObject.transform.position;
                endPos = player.gameObject.transform.position + Vector3.forward * distance1;

                currentLerpTime += Time.deltaTime;
                if (currentLerpTime >= lerpTime)
                {
                    currentLerpTime = lerpTime;
                }
                float perc = currentLerpTime / lerpTime;
                player.gameObject.transform.position = Vector3.Lerp(startPos, endPos, perc);
            }
        }
}

Am I not storing the two positions here?

startPos = player.gameObject.transform.position;
                endPos = player.gameObject.transform.position + Vector3.forward * distance1;

OK yeah, multiple issues with that code that weren’t visible in the original post. Mainly, you seem to be confused about how Lerp works.

Lerp doesn’t move anything. It doesn’t animate. It returns a value that’s C% between A and B, and that’s all it does. If you call it for one frame, it will move the object… one frame.

In order to use it to animate from point A to point B, you need to call it every frame until the movement is completed. There are a lot of ways to do that. Here’s my favorite for most situations:

StartCoroutine(LerpOverTime(startPos, endPos, duration);

IEnumerator LerpOverTime(Vector3 startPos, Vector3 endPos, float duration) {
   for (float t=0f; t < duration; t += Time.deltaTime) {
      player.transform.position = Vector3.Lerp(startPos, endPos, t / duration);
      yield return 0;
   }
   player.transform.position = endPos;
}

You can insert this code (the first line in place of your line 38, the rest as a function in the class), and it will actually do what you thought Lerp did: it kicks off a coroutine, that will run code each frame, and run Lerp repeatedly during that time.
(You’ll want to make sure this is only being called once, in this case by setting startmove to false)

Also, don’t use GameObject.Find. It’s never the best way to find objects, but it’s especially bad in Update.

What is the duration coming from?

You make it up, it’s just a float. I guess it’s equivalent to lerpTime in your code.

How am I suppose to talk to other objects then?

Rgr that.

I’ll work through this so I can learn what you did.

Read the link, it has a lot of examples.

I didn’t see the link at first…Thanks.

@StarManta

Can you explain the IEnumerator?

I’ve seen that before but I don’t understand the logic behind it.

@All_American
Besides the good suggestions here, also look into DoTween or other tween frameworks. It will make such animation a one line breeze.

1 Like