Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 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 /
  • Help Room /
avatar image
0
Question by Prezzo · Mar 31, 2016 at 09:52 PM · coroutineruntimetimeraccuracy

How to do very accurate time measurement

The game I am making aims for measuring human reflexes. For this purpose I must use very accurate counters and timers (accuracy of 1ms).

I have some questions about the best way to write this code.

  • A stopwatch (Stopwatch class) starts when a button is pressed. After some time, the user must press another button as fast as possible. When this happens, the stopwatch stops and sends the time to a database. The signal to stop the timer is given by an onclick event in the Button component. When in the pipeline (Awake- Start- FixedUpdate- Update.....) does unity read out if this button is pressed? Or how does the 'onclick' work exactly, is this really accurate?

  • When the player doesn't press the button for 250 ms, the button changes color. I can't get this accurate. At the moment I use a coroutine with "Yield return new WaitForSeconds(.250f). I checked the accuracy of this with a Stopwatch and found out that the next line of code was executed after about 257ms instead of 250. I know the cause of this problem is that every coroutine is only executed once every frame. Is there a better method than using coroutines? Somebody told me to use event handlers and threads but I'm not sure this will solve it...

Comment
Add comment
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

3 Replies

· Add your reply
  • Sort: 
avatar image
2

Answer by phxvyper · Mar 31, 2016 at 10:09 PM

Unfortunately, in Unity, deltaTime is dependent upon your frame rate. You can define a preferred frame rate of 1000 or higher (1 frame every 1 ms) that way you can get the accuracy you need, but this doesnt guarantee that you'll get a constant frame rate of 1000 or more.

See Application.targetFrameRate for more information. If you want it to render as fast as it possibly can, then set this value to -1. If you don't have much to render or process, and your cpu and graphics card are average or better, then you should easily get 1000+ FPS. Otherwise, you're at a loss.

UPDATE:

WillNode's suggestion to use FixedUpdate unfortunately comes to the same flaws the Update can. FixedUpdate doesn't always necessarily update every 50 ms, or every 1 ms if you set it to that in your Time Manager.

As suggested by Eric5h5 in his reply to this question, you should stray away from Update and FixedUpdate for ms-perfect timing, and instead use InvokeRepeating.

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
1

Answer by WillNode · Apr 01, 2016 at 12:28 AM

For these situations is better to use FixedUpdate instead, as it can do and be called multiple times more accurate than limited-to-devices regular Update. Fixed Update called on every 50 ms, you can change that to 1 ms in Time Manager (but seriously, 1 ms? i did better to set as minimum as 5 ms, since 1 ms is too fast for mobiles).

Coroutines do call and resume in regular Update calls. Luckily, there's a WaitForFixedUpdate which resumes after a FixedUpdate call so: don't use WaitForSeconds, use WaitForFixedUpdate instead.

And for Inputs like Button Click, etc, Happens internally on regular update. you can't do anything with that, so to keep the user convenience, it's better to substract the time as long as last Update be called (deltaTime):

 float time = 0;
 IEnumerator fixedWait()
 {
     //Since this called first at update loop, call Time.time
     time = Time.time;
     //Fixed time after it
     while (time.fixedTime < time + .250f)
     {
         yield return WaitForFixedUpdate(); //Resumed as soon as FixedUpdate call.
     }
     Debug.LogWarning("Timeout:" + (Time.fixedTime - time).ToString());
     //Timeout, Do anything...
 }
 
 //User press the button
 public void CatchClick()
 {
     StopAllCoroutine();
     //Unfornatunely, buttons do call on regular update...
     //So give the user some tolerance as long as deltaTime
     //or half of deltaTime, third, is up to you...
     float finalTime = Time.time - time - Time.deltaTime;
     Debug.Log(finalTime)
 }
 
 //User Start the count
 public void StartCount()
 {
     //StartCoroutine will call at regular update...
     StartCoroutine(fixedWait())
 }

PS : see how it's ordered : http://docs.unity3d.com/Manual/ExecutionOrder.html

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
1

Answer by eppz · Mar 09, 2017 at 08:56 PM

I would definitely don't rely on any runloop (Update, nor FixedUpdate). Do not poll.

On iOS, every touch have a timestamp. Which is extremely accurate. See https://developer.apple.com/reference/uikit/uitouch/1618144-timestamp

Write a native plugin that bridges that into Unity. And just compare those values.

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

8 People are following this question.

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

Related Questions

Need coroutine to render a texture value clamped from 0 to 1 over time 1 Answer

Best way to get code to run at very precise timing? 0 Answers

My code is not working - HELP - IEnumerator Coroutines 0 Answers

Issues with video player coroutine 2 Answers

Coroutine, Timer Local vs Class variable difference 0 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