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?

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 );
    }
}

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.

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).