Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Needed Lerp Solution? Or new Design?

Discussion in 'Scripting' started by PsychoSupreme, Nov 16, 2015.

  1. PsychoSupreme

    PsychoSupreme

    Joined:
    Jun 30, 2015
    Posts:
    4
    Hello,
    I'm attempting to read car positions from a xml file and update their positions in my game.
    I've accomplished this and everything runs from start to finish:
    • Cars spawn
    • Cars move
    • Continue to move
    • Cars are destroyed once path complete
    The issue I'm having is the car's snapping/teleporting to each new position, my goal is to have them move smoothly to each position. I figured this could be done with lerp, but as I read the xml file in my update I'm wondering if it's not possible to use lerp as each car is visited only once in each node/once it's visited again it needs a brand new position.

    I've attached a sample of my code that should be enough to see the problem. The movement to the car's next position is found in determineCar().

    If anyone also knows of a way to also slow down my cars (notice how my update works) that would be helpful as well.

    Code (CSharp):
    1. int readTime = -1;
    2.  
    3.     void Update ()
    4.     {
    5.         readTime++;
    6.  
    7.         readXml ();
    8.     }
    9.  
    10.     //read a node in the xml file
    11.     void readXml ()
    12.     {
    13.         int count = 0;
    14.         //validate each current node
    15.         resetState();
    16.  
    17.         foreach (XmlNode node in nodeList) //for each timestep
    18.         {  
    19.             if (count == readTime)
    20.             {
    21.                 foreach (XmlNode nn in node) //for each vehicle in that timestep
    22.                 {      
    23.                     determineCar (nn);
    24.                 }
    25.                 break;
    26.             }
    27.             else
    28.                 count++;
    29.         }
    30.  
    31.         //delete any items not in latest node
    32.         deleteObjects();
    33.     }
    34.  
    35.     //determine if the current car is already in the scene
    36.     //if not, create and add a new car
    37.     void determineCar (XmlNode curNode)
    38.     {
    39.         GameObject car = alive (curNode);
    40.         //update a car
    41.         if (car)
    42.         {
    43.             updateCarData(ref car, curNode);
    44.             Vector3 newPos = new Vector3(car.GetComponent<CarProperties> ().x,
    45.                                          1.5f,
    46.                                          car.GetComponent<CarProperties> ().y);
    47.  
    48.             car.transform.position = Vector3.Lerp(car.transform.position, newPos, 1);
    49.         }
    50.         //create new car
    51.         else
    52.         {
    53.             car = Instantiate (getCarData(curNode),
    54.                                new Vector3 (float.Parse (curNode.Attributes ["x"].Value), 1.5f, float.Parse (curNode.Attributes ["y"].Value)),
    55.                                new Quaternion(0,0,0,0)) as GameObject;
    56.  
    57.             activeCars.Add(car);
    58.         }
    59.     }
     
    Last edited: Nov 16, 2015
  2. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,745
    Rather than setting the car's position direct from your XML, give the car a script. When you read the XML, call a function on that car with a position and a duration (the time it will take to reach that position). The car will then be responsible for lerping its own position, until it receives its next destination.

    I think you're falling for the classic Lerp misunderstanding. Vector3.Lerp does nothing except return a Vector3 - it doesn't do anything over time. It's used for things that happen over time, but all it does is, give you a point that's between your A and B inputs, which it chooses based on your C input (from 0 to 1, 0 returns A, 1 returns B).

    What you need is a coroutine (in code, it's declared as IEnumerator for reasons too hackish to get into). A coroutine executes some code, then waits for the next frame (or some other condition, but it's usually that one), then executes some more code. That "executes some code" bit is where Lerp comes in.

    Here's a bit of code to help:
    Code (csharp):
    1. StartCoroutine(MoveFromTo(transform.position, newPosition, 1f) );
    2.  
    3. ....
    4.  
    5. IEnumerator MoveFromTo(Vector3 posA, Vector3 posB, float duration) {
    6. for (float t=0f; t < duration; t += Time.deltaTime) {
    7. transform.position = Vector3.Lerp(posA, posB, t/duration);
    8. yield return null;
    9. }
    10. transform.position = posB;
    11. }
    This snippet is something I use all the time (with variations), and it's really, really handy. It's a bastardization of a for loop.
    * Each step in the for loop moves forward by one frame.
    * t is the amount of time we've been in the loop; every time you run through the loop, it gets Time.deltaTime added to it.
    * therefore, t / duration gives you a number from 0 .. 1, which - how about that! - is exactly what Lerp wants in parameter #3
    * "yield return null;" is coroutine-speak for "wait for one frame"
    * You have to set it directly to posB at the end because, the last trip through the loop, it'll only ever be like 99.994321% of the way there.
     
  3. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,848
    Or, consider that for almost every use a new Unity dev tries to make of Lerp, they should be using MoveTowards instead.

    MoveTowards does what most beginners think that Lerp does, and is much easier to use since you don't have to keep track of your starting point and time yourself.
     
  4. PsychoSupreme

    PsychoSupreme

    Joined:
    Jun 30, 2015
    Posts:
    4
    I tried your idea of making each car's script handle the lerping and movement of themselves as opposed to in the reader. Might be my computer, but each car seemed to move in odd patterns as well as disappear in some frames during playback. They were definitely moving in smaller segments at least, but not smoothly.