godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
91k stars 21.17k forks source link

`max` returns NaN under specific conditions #56005

Closed Zylann closed 2 years ago

Zylann commented 2 years ago

Godot version

4.0 092a2861277e7df87aec10516d713d0bf4adba79

System information

Windows 10 64 bits GLES3 GeForce GTX 1060 6GB/PCIe/SSE2

Issue description

I noticed a NaN popped up while I was porting a project to Godot4, and was very confused to find its origin in the following expression:

distance = max(distance - 1 - distance * 0.1, 0)

distance becomes NaN after this. I tried a simple repro but could not get it to happen. So I tried a bit more of the original code, and it started happening:

extends Node3D

@export var distance = 0.0

func _unhandled_input(event):
    if event is InputEventMouseButton:
        if event.button_index == MOUSE_BUTTON_WHEEL_UP:
            assert(not is_nan(distance))
            print("A distance before: ", distance)
            distance = max(distance - 1 - distance * 0.1, 0)
            print("A distance after: ", distance)
            assert(not is_nan(distance))

        elif event.button_index == MOUSE_BUTTON_WHEEL_DOWN:
            assert(not is_nan(distance))
            print("B distance before: ", distance)
            distance = max(distance + 1 + distance * 0.1, 0)
            print("B distance before: ", distance)
            assert(not is_nan(distance))

Still, I have no clue why would NaN originate from this.

Steps to reproduce

With the code above, start the game, and wiggle your mouse wheel back and forth. The game will quickly assert.

Minimal reproduction project

Max.zip

Zylann commented 2 years ago

It does not happen if the second argument of max is 0.0 instead of 0. I suspect a bad type conversion issue.