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

visualize movement Just in time

Discussion in 'Scripting' started by bheydari, Jul 17, 2016.

  1. bheydari

    bheydari

    Joined:
    Jul 17, 2016
    Posts:
    5
    Hi
    I've physic based simulator that generate position of objects with fixed interval of simulation time, So start with unity to visualize this movement. in simple example of single object report file can be like:
    currentTime,currentX,currentY,currentZ
    0,0,0,0
    0.02,2.0,20.0,0
    0.04,4.0,60.0,0
    0.06,6.0,140.0,0
    0.08,8.0,300.0,0
    0.1,10.0,620.0,0
    so i wrote script to read them from file and now have two array. one for times that reported and second, for position of object in each time. I just know vector3.lerp, vector3.movetowards and Update function, so thought about different combination of them and could not understand how to be in specific position in specific time (with smooth move between them). should i use other library or functions?
    Thanks
     
  2. Oribow

    Oribow

    Joined:
    Nov 9, 2012
    Posts:
    38
    Is the file already filed with postions, when Unity starts? In that case, you can just interpolate between two timestamps. When you only have the newest data point avaible, you can either delay unity, so that the unity lacks always a step behind and knows the next datapoint ahead of time, or calculate the current speed of that object and extrapolate that. This though could lead to objects moving in the wrong direction for a ceratain amount of time, untill the next data point comes through. Your essentialy are faced then with the same problem multiplayer games have with lag and players seem to teleport. Give us more details!

    But when I look at you timestamp differences, such techniques might not be nessecesary. With a framerate of 60, the screen only gets updated every 16ms. When you run on 30 fps its even only every 33ms. When your datapoints come in fast enough, a stuttering in movement might not be visible.
     
    bheydari likes this.
  3. bheydari

    bheydari

    Joined:
    Jul 17, 2016
    Posts:
    5
    yes, file is filed when unity starts. could you explain more about "just interpolate between two timestamps"
     
  4. Oribow

    Oribow

    Joined:
    Nov 9, 2012
    Posts:
    38
  5. Oribow

    Oribow

    Joined:
    Nov 9, 2012
    Posts:
    38
    Example:
    Things you need to now:
    Code (CSharp):
    1. Datastamp A: 0,0,0,0
    2. Datastamp B: 0.02,2.0,20.0,0
    3. float timeInterpolationStarted = 0;
    This is what runs in the Update method:
    Code (CSharp):
    1. position = Vector3.Lerp (new Vector3(0,0,0), new Vector3(2,20,0), 1/0.02 * (timeInterpolationStarted  - Time.time));
    Or more generic:
    Code (CSharp):
    1. position = Vector3.Lerp(pointA, pointB, 1/timeBetweenPoints * timeSinceStartedLerpingThisPointPair)
    Thats all, but you have to know the next point eg: pointB in advandced. this means, that Unity will always work on point behind the simulation.
     
  6. bheydari

    bheydari

    Joined:
    Jul 17, 2016
    Posts:
    5
    Thanks, but your solution assumes that speed is constant, as you can see in example Y-Axis movement is not with fixed speed.
     
  7. Oribow

    Oribow

    Joined:
    Nov 9, 2012
    Posts:
    38
    Yes it does that, but on an atomic level. You have to go through each pair of datapoints iterativ. Starting with the first: Simulate, until second point reached. Then next: Simulate, until third point reached and so on. You only know the exact position of the object on a given time defined by the datastamp. Between the datastamps, you have to lerp, because you can't know how the object is actually moving, because you don't have data about that.

    p0 -> lerp -> p1
    p1 -> lerp -> p2
    p3 -> lerp -> p4
    ...
     
  8. mgear

    mgear

    Joined:
    Aug 3, 2010
    Posts:
    8,998
    bheydari likes this.
  9. Oribow

    Oribow

    Joined:
    Nov 9, 2012
    Posts:
    38
    @mgear sure that would work, but he wants smooth movement between datasteps. I agree that a deltatime of 0.02s is so low, that the movement will apear smooth regardless, but lerping between will help smoothing things out. Especially, if the deltatime suddenly increases.@bheydari The leads me to the question will that ever be the case?
     
  10. bheydari

    bheydari

    Joined:
    Jul 17, 2016
    Posts:
    5
    Yes, Thanks in advance, your help made me wrote this Update function, soon will test it and report any result. any comment?

    Code (CSharp):
    1. void Update () {
    2.         float step = Vector3.Distance(Locations[now], Locations[now+1]);
    3.         float distCovered = Vector3.Distance(Locations[now], transform.position);
    4.         float fracJourney = distCovered / step;
    5.         transform.position = Vector3.Lerp(Locations[now], Locations[now + 1], fracJourney);
    6.         if (Time.time - startTimeOfEachLerp[now] > interval){
    7.             now++;
    8.             startTimeOfEachLerp[now] = Time.time;
    9.         }
    10.     }
    @mgear Thanks, I would test and compare results.
     
    Last edited: Jul 17, 2016
  11. Oribow

    Oribow

    Joined:
    Nov 9, 2012
    Posts:
    38
    Ah. That wont work. Right at the begining, transform.position should be equal to Locations[now], so distCovered = 0. FracJourney becomes 0/step = 0. Nothing will change! fracJourney never increments. Why all this complicated math? You only have to implement something like this:

    Code (CSharp):
    1. Vector3[] Locations;
    2.     int currentLoc;
    3.     float timeSinceLerpStart;
    4.     float interval;
    5.     float inverseInterval = 1 / interval;
    6.     // Update is called once per frame
    7.     void Update()
    8.     {
    9.         float deltaTime = Time.time - timeSinceLerpStart;
    10.         if (deltaTime >= interval)
    11.         {
    12.             currentLoc++;
    13.             timeSinceLerpStart = Time.time;
    14.         }
    15.         transform.position = Vector3.Lerp(Locations[currentLoc], Locations[currentLoc + 1], inverseInterval * deltaTime);
    16. }
    Please read up on what lerp actually does. Seems like you think of it different, then it actually is.
     
    bheydari likes this.
  12. bheydari

    bheydari

    Joined:
    Jul 17, 2016
    Posts:
    5
    Thanks for your comment, I understand what you mean, but it is working as i want! I just add some boundary checking, and it is working. but your code is more understandable so i will test it.
     
  13. andre_anastacio

    andre_anastacio

    Joined:
    Feb 21, 2019
    Posts:
    3
    Hi, how was the solution to this? I have the same problem