Timer.time_left won't hit 0?

Godot Version

4.4.dev

This is a curious behavior with Timer that I ran into recently. I tried to check if a timer has finished during _physics_process by doing this:

func _physics_process(delta: float) -> void:
		if $speak_timer.time_left==0:

but turns out this conditional is never true if you don’t manually stop the timer.
I had to instead try:

func _physics_process(delta: float) -> void:
		if $speak_timer.time_left<0.1:

Anyone had similar issue?

update:
TL;DR use get_time_left().

This is how it’s implemented in the engine:

double Timer::get_time_left() const {
	return time_left > 0 ? time_left : 0;
}

Turns out time_left will always be less than 0 when it’s stopped. This somewhat contradicts what’s been said in the doc.

The timer’s remaining time in seconds. This is always 0 if the timer is stopped.

well, actually it would be -1:

void Timer::stop() {
	time_left = -1;
	_set_process(false);
	autostart = false;
}

I think you forgot to set your timer to one_shot, didn’t you?

it was in one_shot. I should just use is_stopped() instead of mingle with these number details.

I tested it with a one-shot timer and it worked correctly; after a while, the remaining time becomes exactly 0 and stays at 0. However, for anything other than this, since there is a slight delay (delta) between each process in the time function, from the perspective of _physics_process, a regular timer restarts after getting sufficiently close to zero. For this, I created a variable that becomes true when the timer ends, and then sets itself to false after being requested by the function. This way, after the timer reaches the end, the condition will be true once.