Double field with OnValueChanged causes infinite callbacks

Issue #662 resolved
Mike Wyatt created an issue

The code that detects changes to double fields with [OnValueChanged] causes the callback to be triggered continuously in three situations when the value is updated inside the callback:

  1. The value is set to NaN.
  2. The field has a [Range] attribute it is set to a value outside the range.
  3. The field has a [Range] attribute and it is set to a value inside the range, but with more precision than the float type supports.

When the value is updated, the callback starts getting called continuously (once per editor frame?), possibly because Odin Inspector doesn’t realize that the value is no longer changing.

To reproduce without Range attribute:

  1. Add this script to a GameObject.
  2. Change the value of a to anything.
  3. Watch the non-stop stream of “Updating …” messages in the Console.
public class OdinBugTester : MonoBehaviour {

    [OnValueChanged(nameof(Refresh))]
    public double a;

    [OnValueChanged(nameof(Refresh))]
    public double b;

    private void Refresh() {
        Debug.Log($"Refresh");
        b = double.NaN;
    }
}

To reproduce with Range attribute, use this code and try setting a to 2 or 0.000130412100757812.

public class OdinBugTester : MonoBehaviour {

    [OnValueChanged(nameof(Refresh))]
    public double a;

    [OnValueChanged(nameof(Refresh))]
    [Range(0, 1)]
    public double b;

    private void Refresh() {
        Debug.Log($"Refresh");
        b = a;
    }
}

I’m using Unity 2019.2.14f1 on a Windows 10 machine.

Comments (9)

  1. Mike Wyatt reporter

    I’ve updated the description with new situations where this same behavior occurs. I believe I have a workaround: not using NaN or Range in my script. These are inconvenient, so a fix would be appreciated!

  2. Tor Esa Vestergaard

    Just like #661, this was apparently related to the fact that float.NaN and double.NaN are not equal to anything, not even themselves. This would make Odin think that any NaN value was being changed every frame, since “oldValue == currentValue” would be false, despite old and current both being NaN, and so Odin would set any NaN value to NaN every frame. I’ve now implemented some custom equality comparer logic for floats and doubles, that consider NaN to be equal to NaN. The fix should be in 2.1.13. Cheers for reporting this

  3. Tor Esa Vestergaard

    If you would like to receive a build with the fix before the next patch release, please contact me on Discord and I’ll get it to you.

  4. Log in to comment