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 sdcur2 · Feb 16, 2018 at 03:08 PM · c#timerfloat

Timer float not evaluating correctly when I check if it's less than another number

I have a timer for some code that runs every FixedUpdate. The code looks like this:

 float timer = 0;
 
 if (timer <= 0.2f)
 {
     //do stuff
     timer += Time.fixedDeltaTime;
 {

I've used timers like this many times, with no issues. But this time I've noticed that the loop performs an extra iteration, because when the timer reaches a value of 0.2, it is evaluating as being greater than the 0.2f it's being compared to.

This appears to be because of the inaccuracy of floating point numbers. But, all the documentation I've been able to find suggests that this is the accepted approach to timers, but this must be a problem that crops up often. Is there some more accurate way of using a timer that is accepted as the better practice?

Comment
Add comment · Show 4
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 TreyH · Feb 16, 2018 at 03:11 PM 2
Share

probably unrelated, but should if (timer <= 02.f) be if (timer <= 0.2f)

avatar image Deathdefy · Feb 16, 2018 at 03:12 PM 0
Share

Your description makes it sound like you want it to be 1/5th of a second(0.2f). Your code looks to be 2 seconds(02.0f). Is this intentional or just a simple reading error?

avatar image sdcur2 · Feb 16, 2018 at 08:21 PM 0
Share

Yes, sorry, that was a typo. I've corrected it to 0.2f

avatar image Harinezumi · Feb 19, 2018 at 11:18 AM 0
Share

This is really weird, I use similar code all the time and it works as expected.
Could you post some more code (preferably by editing your question) to see more context? I would like to understand what is happening, and of course, help.

Another question: have you tried moving the timer += Time.fixedDeltaTime; outside the condition and see what happens?

3 Replies

· Add your reply
  • Sort: 
avatar image
1

Answer by ransomink · Feb 19, 2018 at 10:30 AM

You can do at least two different approaches: The first one rounds the float to two decimal places to avoid floating point imprecision.

 private int   _iteration;
 private float _timer = 0f;
 
 void FixedUpdate()
 {
     if ( _timer < 0.2f )
     {
         _iteration++;
         _timer += Time.fixedDeltaTime;
         _timer  = ( float )System.Math.Round( _timer, 2 );
         Debug.Log( "Iteration: " + _iteration + " | Timer: " + _timer );
     }
 }


The second one uses Mathf.Approximately to compare two floats using Epsilon as a tolerance.

 private int   _iteration;
 private float _timer = 0f;
 
 void FixedUpdate()
 {
     if ( !Mathf.Approximately( _timer, .2f ) )
     {
         _iteration++;
         _timer += Time.fixedDeltaTime;
         Debug.Log( "Iteration: " + _iteration + " | Timer: " + _timer );
     }
 }
Comment
Add comment · Show 2 · 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 ransomink · Feb 19, 2018 at 03:00 PM 1
Share

I've tested both versions and it works fine. I believe the problem is the fixedDeltaTime itself because it will always increment the same value. During my test, some values, like 1, was listed as 0.99999~ and so on. This was before and why I added rounding, so that's why you're getting an extra iteration. Even though fixedDeltaTime increments at a constant rate it has floating point imprecision; So ( timer < .2f ) will run again even when timer is equal to .2f...

avatar image ransomink · Feb 20, 2018 at 09:50 PM 0
Share

@sdcur2 Did it work for you?

avatar image
0

Answer by HenryStrattonFW · Feb 18, 2018 at 08:42 AM

Have you tried separating the tests, so the < can be done as currently but instead of = test using Mathf.Approximately. This may just be an issue with floating point imprecision.

Comment
Add comment · Show 2 · 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 sdcur2 · Feb 19, 2018 at 03:02 AM 0
Share

Even if I remove the equality entirely, and just do timer < 0.2f, it does not evaluate correctly (when the timer is also 0.2f). It does one more iteration and only evaluates as being greater than when the timer is 0.22f.

It does evaluate correctly if I cast both the timer and the 0.2f to decimal inside the if statement.

avatar image HenryStrattonFW sdcur2 · Feb 19, 2018 at 10:47 AM 0
Share

Well if you remove the equality check then it will and should to one more iteration as 0.2f is not less than 0.2f

avatar image
0

Answer by Harinezumi · Feb 19, 2018 at 03:11 PM

Reading ransomink's answer I've just realised that the real issue is that you ( @sdcur2 ) would like it to execute what you have in the block an exact number of times. If this is the case, a better solution is to use an exact counter, an int:

 private int iterationCounter = 0;
 private int numIterations = 10;
 
 private void FixedUpdate () {
     if (iterationCounter < numIterations) {
         iterationCounter++; // I recommend to first increment the condition and only after do things to make sure that the condition variable is updated
         // do stuff;
     }
 }

Using a float for timers is accepted in other cases, because there you care less about the number of times, you care about the duration and the progress of the variable (e.g. in case of lerping).

Comment
Add comment · Show 2 · 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 sdcur2 · Feb 20, 2018 at 02:33 PM 0
Share

It's a situation where I do care about duration - it's an animation that I want to last exactly a fifth of a second. In general, I always try to use variables rather than hard-coding that sort of thing, in case the value changes in future. But I guess using fixedDeltaTime will always be in increments of 0.02 seconds, and I should just treat it as an invariable number - which means I could just specify an exact number of times.

avatar image Harinezumi sdcur2 · Feb 20, 2018 at 03:46 PM 0
Share

Then I did not understand the issue after all :D

Working with time and floats on a computer you will never be able to execute things exactly, you will always have to expect imprecision, and clamp the values or compare approximately.
Btw, you can actually change fixedDeltaTime in the Editor, in Edit -> Project Settings -> Time -> Fixed Timestep setting, but it is not recommended.

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

453 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 avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Timer instantly sets to zero 1 Answer

Create a float with only 1 decimal? C# 1 Answer

,Why isn't the clock speed being affected by the float "clockSpeed"? 0 Answers

One script says the variable is 0 but the other says -37 1 Answer

currentSpeed doesnt change when pressing Shift (C#) 1 Answer


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