Search code examples
c#unity-game-enginelerp

Lerp not consistently smooth for car movement


I am simulating cars driving through a road network given four columns of data time, id, x and z where a car with id id is located at x,0,z at time t Here is a sample:

t   id  x   z
957,1,-1.50,250.07
958,1,-1.50,232.39
959,1,-4.50,209.72
960,1,-4.50,193.05
961,1,-4.50,176.39
962,1,-4.50,159.72
963,1,-4.50,143.05
...

At the moment, I'm able to spawn cars and update their positions as time elapses and according to the data. I'm stuck on how to more realistically simulate car movement, instead of the car simply popping from point to point.

I am using Vector.Lerp but it jump without consistent, smooth movement:

car.transform.position = 
    Vector3.Lerp(car.transform.position, nextPosition, Time.deltaTime);

At each second, I check the data above to find the coordinates of the car at the current second. Those coordinates are passed as nextPosition into the above Lerp function. This means that the car is 'Lerping' from point to point, every second.

How can I make the movement smoother? The position updates are every second and therefore the car needs to reach the next position in 1 second.


Solution

  • You need to use the moveToX function which moves object to a position within x seconds. It simplifies this whole stuff. All you have to do now is loop over each position in the list, and the moveToX function and provide the time (1 sec) the object must be there.

    This moveToX function works by using Time.deltaTime to increment a counter variable until it reaches the target time specified. The t is calculated by dividing that counter with the target time resulting to 0 and 1 values since that's what t in Vector3.Lerp expects. All these must be done in a coroutine function because coroutine simplifies waiting in a function.

    public GameObject car;
    public List<Vector3> pos;
    bool isMoving = false;
    
    IEnumerator MoveCar()
    {
        //Loop over each postion
        for (int i = 0; i < pos.Count; i++)
        {   
            //Get next position
            Vector3 nextPosition = pos[i];
            //Move to new position within 1 second
            yield return StartCoroutine(moveToX(car.transform, nextPosition, 1.0f));
        }
    }
    

    then you can start the movement by calling the coroutine function:

    void Start()
    {
        StartCoroutine(MoveCar());
    }