Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
2
Question by spacepilot · Jan 09, 2012 at 03:37 AM · yield

How to get precise timer

Using the function WaitForSeconds doesn't seem to produce exact results. Especially when waiting for milliseconds instead of seconds. Is there some other way to let a function wait a specific time?

Example:

 var waitingtime : float = 0.1;
 var i : int;
 @HideInInspector()
 var time1 : float = 0;
 @HideInInspector()
 var time2 :float = 0;
 @HideInInspector()
 var deltatime : float = 0;
 
 function Start(){
     for (i = 1; i < 16; i++){
         time1 = Time.time;
             yield WaitForSeconds (waitingtime);
         time2  = Time.time;
         deltatime = time2-time1;    
         Debug.Log("Attempt No: " +i +" ;Waited time: " +deltatime +"s - it should be: " +waitingtime +"s.");    
         yield WaitForSeconds(1); //Pause until next round - to give debugger a bit refresh-time.
     } //end for i
 } //endfunc Start

This script, attached to some object produces an output similar to this, after hitting the Start-Button in Unity:

Attempt No: 01 ;Waited time: 0.3533334s - it should be: 0.1s.

Attempt No: 02 ;Waited time: 0.1527811s - it should be: 0.1s.

Attempt No: 03 ;Waited time: 0.1974149s - it should be: 0.1s.

Attempt No: 04 ;Waited time: 0.1044042s - it should be: 0.1s.

Attempt No: 05 ;Waited time: 0.1999474s - it should be: 0.1s.

Attempt No: 06 ;Waited time: 0.2078395s - it should be: 0.1s.

Attempt No: 07 ;Waited time: 0.1046262s - it should be: 0.1s.

Attempt No: 08 ;Waited time: 0.1062851s - it should be: 0.1s.

Attempt No: 09 ;Waited time: 0.1296844s - it should be: 0.1s.

Attempt No: 10 ;Waited time: 0.1247978s - it should be: 0.1s.

Attempt No: 11 ;Waited time: 0.1004639s - it should be: 0.1s.

Attempt No: 12 ;Waited time: 0.1252518s - it should be: 0.1s.

Attempt No: 13 ;Waited time: 0.1074142s - it should be: 0.1s.

Attempt No: 14 ;Waited time: 0.1060486s - it should be: 0.1s.

Attempt No: 15 ;Waited time: 0.217804s - it should be: 0.1s.

It's easy to see that it rarely pauses for the desired time (4 times out of 15 attempts).

Comment
Add comment · Show 2
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Peter G · Jan 09, 2012 at 03:46 AM 0
Share

Depending on exactly what you're trying to do, you might want to try threading.

avatar image spacepilot · Jan 09, 2012 at 03:56 AM 0
Share

I want a function to pause for an exact amount of time.

Edit: Exact means at least two digits after the second-value, e.g: 0.25s

Edit 2: As far as I understood the documentation, WaitForSeconds is a co-routine, running in parallel to the script while it waits for this co-routine to finish. I guess this way the developers avoided the game to freeze for the waiting-time. The script pauses but the game doesn't. Therefore WaitForSeconds also should be framerate-independent. The only thing that matters is the delay between the end of the co-routine and the next frame to continue the script. This is because the function Update gets called once per frame.

Example: Assu$$anonymous$$g Update is called 24 times per second (is this value correct?), we have 1s/24 = 0.04166666s = 41.6666 ms per frame.

This is the maximum additional time WaitForSeconds can get because of this timegap (error-tolerance). So the worst case is this: The co-routine ends exactly when a frame just got loaded and the function needs another frame to notice that. The measured time then is waitingtime + 0.041 seconds.

However, as seen in the example above, this is barely happening. The total time is a lot bigger. In some tests it also was too small. $$anonymous$$eaning, the function is crap! I need something else.

4 Replies

· Add your reply
  • Sort: 
avatar image
0

Answer by spacepilot · Jan 09, 2012 at 01:15 PM

I tried writing a custom script but I can't use it with the yield-command:

 function WaitForMilliSeconds(ms : float){
     var timecapture1 : float = 0;
     var timecapture2 : float = 0;
     ms = ms / 1000;    
     timecapture1 = Time.time;
     timecapture2 = timecapture1;
     while (timecapture2-timecapture1 < ms){  // = Until [difference] >= ms
         timecapture2 = Time.time;        
     }//went
 }//Endfunc WaitForMilliSeconds

So when I call this function with yield now:

     yield StartCoroutine(WaitForMilliSeconds(100));

The compiler says:

BCE0023: No appropriate version of 'UnityEngine.MonoBehaviour.StartCoroutine' for the argument list '(void)' was found.

What am I doing wrong? Isn't it what yield and Coroutine is for? The script shall pause until the function finshes (without slowing down the whole game).

Comment
Add comment · Show 5 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image aldonaletto · Jan 09, 2012 at 01:54 PM 1
Share

Your function WaitFor$$anonymous$$illiSeconds should have a yield to become a coroutine and be able to be called that way - but it would not work better than WaitForSeconds, because coroutines run in the update cycles, which are synced to the frame rendering process (very unpredictable, for sure).
Rumor has it the InvokeRepeating is the most precise ti$$anonymous$$g tool you have in Unity (http://unity3d.com/support/documentation/ScriptReference/$$anonymous$$onoBehaviour.InvokeRepeating.html)

avatar image spacepilot · Jan 09, 2012 at 02:14 PM 0
Share

This looks interesting! To avoid confusions directly at the beginning: The documentation says the command accepts a method. I'm new to object-oriented world, so please forgive my silly question: This method seems to be a function in the example. Can this function have a return-value then?

avatar image syclamoth · Jan 09, 2012 at 02:17 PM 0
Share

Refer previous thread about coroutines: No, it can't, and for all the same reasons (initiating function can't wait for return values, etc. etc.).

avatar image aldonaletto · Jan 09, 2012 at 02:25 PM 1
Share

I don't know if the function may return a value, but for sure you won't be able to use it because the system calls the function, not you. If you need it to return any value, store it in a member variable (variable defined outside any function).

avatar image spacepilot · Jan 09, 2012 at 05:28 PM 0
Share

This was helpful. But how do I finally get a timer out of it? When changing my function into a co-routine with a lower 42ms-limit as you said, I have the advantage that it will run asynchronous without game-influence. The function could output a value into some member-variable at any time so that the main-script also can react on it whenever it wants.

Question: How do I pause the asynchronous co-routine for 10ms? Or in other words: How do I stop the InvokeRepeating-command afterwards? The example in the documentation shows how projectiles get fired. There must be a way to also stop firing. $$anonymous$$g. when the magazine is empty.

avatar image
0

Answer by BTables · May 23, 2014 at 01:39 AM

I think you are misunderstanding what coroutines do, Unity doesn't multithread coroutines at all which is causing the inconsistent yield results. (Didn't you ever wonder why everything is magically threadsafe?)

Unity does its normal update loop of:

  • FixedUpdate()

  • Call coroutine that has yielded WaitForFixedUpdate until it yields again

  • Update()

  • Call all coroutines that have yielded for atleast long enough except WaitForFixedUpdate until it yields again

  • LateUpdate()

  • RenderStuff()

When your coroutine is called, nothing else is done until you yield, trying to use a busy wait in a coroutine will cause no more frames to be rendered until you yield again which is a very bad idea.

I haven't delved into real threading in Unity yet, but this is much more hardcore stuff that unity won't hold your hand through like coroutines. Which opens up a can of worms around thread safety and deadlocks which aren't to be taken lightly.

Here are the docs on when coroutines are called:

  • yield; The coroutine will continue after all Update functions have been called on the next frame.

  • yield WaitForSeconds(2); Continue after a specified time delay, after all Update functions have been called for the frame

  • yield WaitForFixedUpdate(); Continue after all FixedUpdate has been called on all scripts

  • yield WWW Continue after a WWW download has completed.

  • yield StartCoroutine(MyFunc); Chains the coroutine, and will wait for the MyFunc coroutine to complete first.

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
0

Answer by Tarlius · May 23, 2014 at 06:23 AM

Waiting for an EXACT amount of time is impossible. (shcipwa's answer gets this quite well). Although even with threads you'll still be a little out (analogue vs digital). The real question is what are you trying to achieve? The correct approach will probably be see how far "over" you went and deal with it somehow.

For example, if you are writing the 0.1 part of a clock (yes, I actually came across a clock written using logic like this! A 60s game took about 70s, varying wildly depending on the platform >.>; ), you need to carry over the missed part (or use (int)(Time.time % 0.1) or something)

Also, to get such varying results, you might have other performance problems... Are you doing some heavy calculations in this waiting time? To wait 0.31s on a 0.1s wait you are running at less than 5fps...

If you are doing physics calculations you might be able to used FixedUpdate(). The deltaTime in fixed update is fixed (but its also fake! But then so are most of the time functions...)

So back to the question: You can't. You'll have to fake it. What are you trying to do?

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
0

Answer by chernobyyl · Sep 22, 2020 at 02:52 PM

I know im 6 years to late and nobody will probably answer but would it be possible to take the time from an online timer with an api?

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

10 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Yield in loop never returns. [Solved] 0 Answers

www class blocks script execution 1 Answer

Why Is yield return new WaitForSeconds() not working 2 Answers

pause charactercontroller movement briefly? 1 Answer

Definition of Script.function() depends on Script.function()... 3 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges