Search Unity

[Solved] How to sample transform.position with a precision of a frequency of 60Hz with Unity3D

Discussion in 'Scripting' started by probitaille, Nov 21, 2016.

  1. probitaille

    probitaille

    Joined:
    May 5, 2015
    Posts:
    34
    Actually, I use the InvokeRepeating method to invoke another method every 1/x seconds. The problem is that the precision of the delay between the invoke and the data I got is not good.

    Here's my code:

    Code (CSharp):
    1. public class Recorder : MonoBehaviour {
    2.  
    3. public float samplingRate = 60f; // sample rate in Hz
    4. public string outputFilePath;
    5.  
    6. private StreamWriter _sw;
    7.  
    8. private List<Data> dataList = new List<Data>();
    9.  
    10. public void OnEnable()
    11. {
    12.  
    13.     InvokeRepeating("SampleNow", 0, 1 / samplingRate);
    14. }
    15.  
    16. public void OnDisable()
    17. {
    18.     _sw = System.IO.File.AppendText(outputFilePath);
    19.  
    20.     for (int k=0; k< dataList.Count; k++)
    21.     {
    22.         _sw.WriteLine("t {0} x {1} y {2} z {3}",
    23.            dataList[k].time, dataList[k].x, dataList[k].y, dataList[k].z);
    24.     }
    25.  
    26.     _sw.Close();
    27.     CancelInvoke();
    28. }
    29.  
    30. public void SampleNow()
    31. {
    32.     dataList.Add(new Data(Time.time, transform.position.x, transform.position.y, transform.position.z));
    33. }
    34.  
    35. public class Data
    36. {
    37.     public float time;
    38.     public float x;
    39.     public float y;
    40.     public float z;
    41.  
    42.     public Data(float time, float x, float y, float z)
    43.     {
    44.         this.time = time;
    45.         this.x = x;
    46.         this.y = y;
    47.         this.z = z;
    48.     }
    49. }
    So, with this, I can get this kind of result:

    Code (CSharp):
    1. t 0 x 0 y 0 z 0
    2. t 0.02 x 0.283776 y -0.76 z 0
    3. t 0.04 x 0.599808 y -0.52 z 0
    4. t 0.06 x 0.599808 y -0.52 z 0
    5. t 0.08 x 0.599808 y -0.52 z 0
    6. t 0.09999999 x 0.599808 y -0.52 z 0
    7. t 0.12 x 0.599808 y -0.52 z 0
    8. t 0.14 x 0.599808 y -0.52 z 0
    9. t 0.16 x 0.599808 y -0.52 z 0
    10. t 0.18 x 0.599808 y -0.52 z 0
    11. t 0.2 x 0.599808 y -0.52 z 0
    12. t 0.22 x 0.599808 y -0.52 z 0
    13. t 0.24 x 0.599808 y -0.52 z 0
    14. t 0.26 x 0.599808 y -0.52 z 0
    15. t 0.28 x 0.599808 y -0.52 z 0
    16. t 0.3 x 0.599808 y -0.52 z 0
    17. t 0.32 x 0.599808 y -0.52 z 0
    18. t 0.3338465 x 0.599808 y -0.52 z 0
    19. t 0.3338465 x 0.2918357 y -0.7538424 z 0
    20. t 0.34 x 0.2918357 y -0.7538424 z 0
    21. t 0.3539519 x 0.2918357 y -0.7538424 z 0
    22. t 0.3539519 x 0.6092016 y -0.5125771 z 0
    23. t 0.3705226 x 0.6092016 y -0.5125771 z 0
    24. t 0.3870888 x 0.8340279 y -0.3137283 z 0
    25. t 0.4036556 x 0.9750986 y -0.114934 z 0
    26. t 0.42 x 0.9865224 y 0.09031145 z 0
    27. ...
    As you can see in this result, I can collect duplicate position for different time (t=0.04 to t=0.32) and worst, I can get duplicate time (t=0.3539519) with different positions (giving an infinite acceleration).

    In fact, the gameobject analysed moved with a linear fonction in time, doing a circle in the axis X-Y over 20sec.

    So, this code doesn't give me a good precision for a scientific analyze.

    What can I do to get more precision with Unity3D?
     
  2. MD_Reptile

    MD_Reptile

    Joined:
    Jan 19, 2012
    Posts:
    2,664
    I don't know for sure how much it would help accuracy, but using FixedUpdate with a specific fixed delta time, might work for that sort of thing. That generally gets called at the right time everytime, when the game runs smooth anyway...

    Good luck!
     
    AndyGainey likes this.
  3. AndyGainey

    AndyGainey

    Joined:
    Dec 2, 2015
    Posts:
    216
    (expanding on MD_Reptile): For this sort of thing, I think you'd be better off using FixedUpdate(), setting the interval to the duration you want (Edit menu -> Project Settings -> Time -> Fixed Timestep), and making sure that all of the relevant game mechanics get updated within FixedUpdate(), instead of Update(). The latter is better for stuff that represents the game state to the player (such as rendering) but doesn't actually modify the game state in any time-sensitive fashion, and the former is good for behaviors that benefit from highly predictable timing. (The precision might be "fake" in terms of real-time processing, but as far as the game simulation is concerned, each time step will seem to be exactly the correct duration.)
     
  4. probitaille

    probitaille

    Joined:
    May 5, 2015
    Posts:
    34
    Oh thank you. This looks like more constant, yes. But, changing Fixed Timestep will affect all physics of my game I supposed. Is this true?
     
  5. AndyGainey

    AndyGainey

    Joined:
    Dec 2, 2015
    Posts:
    216
    Yes, that is a potential drawback. If you need a custom interval for the data sampling that differs from physics, I'd recommend still using FixedUpdate(), but only sampling data once every n fixed update frames to get approximately the sampling rate that you're looking for. If you actually need to sample at a higher frequency than your physics, then you're probably out of luck, because nothing is going to change from one interval to the next. I'm not aware of any way to automatically get interpolated values for stuff between physics frames, though you could always perform such interpolations manually. (Within each FixedUpdate(), loop n times, incrementing time by a duration that is a fraction of the fixed timestep, and estimating everything's position/orientation based on its velocities and other physical properties. Record the data once each iteration, and hence n times each fixed update frame. But it'd be messy and approximate.)
     
  6. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    Most likely only if you didn't bother multiplying by fixedDeltaTime
     
  7. probitaille

    probitaille

    Joined:
    May 5, 2015
    Posts:
    34
    Thank you for your response. Using FixedUpdate() is actually the simplest solution with Fixed Timestep. :)