0

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.

rafvasq
  • 1,512
  • 3
  • 18
  • 48
  • `Lerp` used to go from "where I am now" to a fixed location is not linear. Imagine instead of `Time.deltaTime` it was 0.5: "Move half way to your destination. Half again. Half again. Half again." https://en.wikipedia.org/wiki/Zeno%27s_paradoxes – Draco18s no longer trusts SE Jun 05 '18 at 17:16
  • 1
    Take a look at this for reference https://docs.unity3d.com/ScriptReference/Vector3.Lerp.html About the paradox, quantized space solved it. – Rodrigo Rodrigues Jun 05 '18 at 18:04
  • @RodrigoRodrigues Thank you for the link, I've taken a look at it and I've played with `t` in the `Lerp` function similarly to the referenced link but the result is still jumpy. – rafvasq Jun 05 '18 at 18:44
  • How do you get `nextPosition`? Just need to know how you get the next position to move the car to. – Programmer Jun 05 '18 at 18:48
  • @Programmer `nextPosition` is the coordinates at the current time. Referring to my sample data above, at `t = 958`, `nextPosition = (-1.50, 0, 232.39)` – rafvasq Jun 05 '18 at 18:52
  • I am not asking you about the vector value. I am asking how you get the next value to move the car to. Also, you mentioned time=958, note that I have no idea what that is. It will take 958 seconds to reach the destination? – Programmer Jun 05 '18 at 19:15
  • @Programmer, sorry about that. I've updated my question with more information regarding my sample data and my `Lerp` function – rafvasq Jun 05 '18 at 19:24
  • I'm not an expert in unity but I think this is something that might be better off done in the FixedUpdate method. I've also always modulated the last parameter to lerp with a scaling value, in this case say the car speed. – asawyer Jun 05 '18 at 19:34
  • Ok, the car must reached it's destination within 1 sec. I get that. How you get the next position to move the object is what I've been asking for so long. I have a feeling you have list of positions you are moving the objects to or from a file. That place you get the next position is what I am trying to know. Maybe add it? @asawyer FixedUpdate is used to move Rigidbody objects. If there is not RB invloved then that's unnecessary. – Programmer Jun 05 '18 at 19:37
  • @Programmer, that's right... the data I provided in my question is the "list of positions" I'm moving an object to over time. – rafvasq Jun 05 '18 at 19:39
  • @Programmer Gotcha, thank you! – asawyer Jun 06 '18 at 12:41

1 Answers1

2

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());
}
Programmer
  • 121,791
  • 22
  • 236
  • 328