Search Unity

Stopwatch loop

Discussion in 'Scripting' started by benjaminver89, Oct 7, 2015.

  1. benjaminver89

    benjaminver89

    Joined:
    May 14, 2015
    Posts:
    30
    I try to get position of an object every 20ms.

    But my animation start after timertest()....

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using System.Diagnostics;
    4. public class Timer : MonoBehaviour {
    5.  
    6.     Stopwatch _timer;
    7.     Stopwatch _timer2;
    8.     void Start () {
    9.         _timer = new Stopwatch ();
    10.         _timer.Start();
    11.         _timer2 = new Stopwatch ();
    12.         _timer2.Start();
    13.         timertest ();
    14.     }
    15.  
    16.     void timertest(){
    17.         while (_timer2.ElapsedMilliseconds<60000) {
    18.             if(_timer.ElapsedMilliseconds>=20){
    19.                 print (_timer.ElapsedMilliseconds);
    20.  
    21.                 //Get element position
    22.  
    23.                 _timer.Stop();
    24.                 _timer.Reset();
    25.                 _timer.Start ();
    26.             }
    27.         }
    28.     }
    29. }
    30.  
     
  2. LeftyRighty

    LeftyRighty

    Joined:
    Nov 2, 2012
    Posts:
    5,148

    Code (csharp):
    1.  
    2. float storedTime;
    3.  
    4. void Update()
    5. {
    6. if(Time.time > storedTime + 20)
    7. {
    8. //reset
    9. storedTime = Time.time;
    10. //do stuff
    11. }
    12. }
    13.  


    nevermind, Star got a handle on what you meant by your last line... coroutine is the way forward, still not sure you need all the stopwatch doohicky stuff
     
  3. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,775
    You need to make that a coroutine! Right now, the game is just going to run your function for a full 60 seconds because your function never says "Go ahead, everything else in the game, I'll wait here." Your function is just constantly asking the CPU "Is it done yet? Is it done yet? Is it done yet?"
    Code (csharp):
    1.  
    2. void Start() {
    3.         _timer = new Stopwatch ();
    4.         _timer.Start();
    5.         _timer2 = new Stopwatch ();
    6.         _timer2.Start();
    7. StartCoroutine(timertest());
    8. }
    9. IEnumerator timertest() { //note that the return type is not void
    10. while (_timer2.ElapsedMilliseconds<60000) {
    11.             if(_timer.ElapsedMilliseconds>=20){
    12.                 print (_timer.ElapsedMilliseconds);
    13.  
    14.                 //Get element position
    15.  
    16.                 _timer.Stop();
    17.                 _timer.Reset();
    18.                 _timer.Start ();
    19.             }
    20. yield return null; // When you're in a coroutine, this effectively means "wait for a frame"
    21.         }
    22. }
    That said, as LeftyRighty posted, there are much better ways of doing this. You should definitely use Unity's Time class rather than C#'s internal stopwatches - Time.time will give you a number that is consistent for an entire frame, while C#'s will keep advancing over the course of the frame.
     
  4. benjaminver89

    benjaminver89

    Joined:
    May 14, 2015
    Posts:
    30
    It seems working faster with coroutine, but my animation always starts after... I need that animation plays in the same time.
    I don't wanna use time between frames : i wanna send some kind of "realtime" information to another hardware component. So i need exactly 20 or 10 ms between each commands sent.
    Is there a way to limiting cpu solicitation?
     
    Last edited: Oct 8, 2015
  5. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,775
    Oh. In that case, I think you'll need to look into running this code on a different thread - there's nothing in Unity that will always execute code at specific time intervals. (FixedUpdate imitates specific time intervals, and for games the imitation works great, but if you use that to send out info to other hardware you'll get staggered output. e.g. if a given frame takes 60 ms to calculate and render, the next frame you'd see 3 FixedUpdate's running instantly)

    I haven't done anything with threads, but there is sample code on the web that can help you out (here's one from the forums)
     
  6. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,775
    Oh, and here's this, that is probably precisely what you want.
     
  7. benjaminver89

    benjaminver89

    Joined:
    May 14, 2015
    Posts:
    30
  8. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,775
    It's not so much "big problems" as just something you'll have to account for. Instead of accessing transform.position within your thread, you set myPosition = transform.position in Update and access myPosition in the thread, that sort of thing.

    I did not know about the 15 ms resolution thing. I'd recommend that you try it anyway - several answers in that post uses phrases like "typically defaults to" which suggests to me that in some platforms/environments it may not apply.
     
  9. benjaminver89

    benjaminver89

    Joined:
    May 14, 2015
    Posts:
    30
    I tried the Thread sample (that seems works well), but i'm in trouble...
    if i compute myPosition in Update() function, I may have the same value for many loop : updat is a lot slower than 10-20ms.
     
  10. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,775
    Well, depends on your framerate, but yes, you should not expect that Update will be called extremely often, and your code should be written to account for that. However, I'm not sure I see how this is an issue - your hardware will be sent the object's latest position in each loop. It sounds like you're asking for your hardware to receive data that happens at a higher framerate than the actual game?

    In other words, you're asking for data that simply doesn't exist. If your goal is for the data to appear smooth, then you're probably going to have to invent some data. Most likely solution would be to interpolate the data between game frames - use the most recent position, the position before that, and the most recent Time.deltaTime to smoothly move from the second-to-last frame's data to the current frame's data. Does that make sense?

    You mentioned early on that you had an animation running concurrently. If that animation is the ultimate source of your data here, you could use the AnimationCurve class to make the data sent to your hardware more accurate/smooth. If you have a public AnimationCurve variable you can edit the curve in the inspector, and then use AnimationCurve.Evaluate with the current system time as your parameter.
     
  11. benjaminver89

    benjaminver89

    Joined:
    May 14, 2015
    Posts:
    30
    Yes i need to do a fast and constant loop.
    That makes sens.

    So, i should :
    -add a buffer where I store positions for some frames (in update)
    -send it to my thread where i wrote my 10ms loop
    -within i do my interpolation from data stored in buffer.

    For smooth motion, it seems ok, but if i wanna add vibration?
    I should add a bool Vibration in my function.
    Seems correct?
     
  12. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,775
    Sounds about right, yeah.
     
  13. benjaminver89

    benjaminver89

    Joined:
    May 14, 2015
    Posts:
    30
    Using AnimationCurve and Thread works well.

    Next probleme will be for simple curve editing. I use the curve editor asset, but it's not perfect.

    it's a too bad that the handling of curves, loading and recording by scripting is so difficult. The tools in the editor is yet so effective.
     
    Last edited: Oct 9, 2015