"Clear and invalidate timer by handle" doesn't work

I can’t understand why this works so strangely?

Then

And

First I get “truefalse”. After 3 seconds, I get “truetrue”. But after 13 seconds I get “truefalse” instead of “falsefalse”. Why?

I recreated the same setup and yes, one of them doesn’t get invalidated. It seems to me that the one you create first (not call first, but create a node in the blueprint) doesn’t get invalidated, regardless the sequence of their launch.

Weird.

Active means the Handle has received a timer (same as your definition of valid) but not executed yet. The moment it executed it will be not active anymore except if it is looping. This is I believe what you wanted.

0 false false

3 true true

3.001 false true

13 false true

13.001 false false

IsValid is used for object reference check. IsTimerActiveByHandle is used if the Timer Handle is valid (active). Try it in your case.

Also I think your are confusing the name ClearAnd Invalidate TimerByHandle. Name should
have been ClearAnd Deactivate TimerHandle for consistency.

I checked in the old version and it worked as it should. This is obviously a bug, but go to 4.20.3 because of this?

And I cannot understand the logic of this error and not repeat the same thing in another situation.

This isn’t weird at all. If you check IsValid function C++, it tells you This does not indicate that there is an active timer that this handle references, but rather that it once referenced a valid timer.

/**
 * Returns whether the timer handle is valid. This does not indicate that there is an active timer that this handle references, but rather that it once referenced a valid timer.
 * @param Handle		The handle of the timer to check validity of.
 * @return				Whether the timer handle is valid.
 */
UFUNCTION(BlueprintPure, meta=(DisplayName = "Is Valid", ScriptName = "IsValidTimerHandle"), Category="Utilities|Time")
static bool K2_IsValidTimerHandle(FTimerHandle Handle);

What you want to use instead of IsValid is IsTimerActiveByHandle:

268342-j-timer.png

Then you’ll get the ff. result in your case:

false false -> no timers are active yet
true  false  -> timer1 is active and waiting for 3 secs, timer2 is not active yet
false true   -> timer1 executed and now inactive, timer2 is active and waiting for 10 secs
false false  -> timer1 was already inactive but still invalidated, timer2 executed and still active but then invalidated immediately

Additionally, here’s what it says about IsValidTimerHandle (IsTimerActiveByHandle) in code:

/**
 * Returns true if a timer exists and is active for the given handle, false otherwise.
 * @param Handle		The handle of the timer to check whether it is active.
 * @return				True if the timer exists and is active.
 */
UFUNCTION(BlueprintPure, meta=(DisplayName = "Is Timer Active by Handle", ScriptName = "IsTimerActiveHandle", WorldContext="WorldContextObject"), Category="Utilities|Time")
static bool K2_IsTimerActiveHandle(UObject* WorldContextObject, FTimerHandle Handle);

But I don’t want to know if it is active. I created a timer and it became valid. When it ended, it became inactive, but valid. This means that when I invalidate it, it should become invalid. And I think the answer should be:
0 sec: false false.
0,1 sec: true false.
3 sec: true true.
13 sec: false false (but not “true false”).
But it is not and I get “true false”

You want to say that when I invalidate it (in “Test 2”), it will remain valid? I understand you, but I think you did not understand me. Maybe because of my English, I cannot correctly explain that after the “Clear and invalidate timer” node, it should become invalid. But it continues to be valid. If you repeat my example, you will see what I am talking about.

I completely understand you and I did your test befor posting above and your example is happening as you said.

That is because you should not use IsValid because you will not get what you wanted. IsTimerActiveByHandle is what you want, try it.

Also, Timer gets invalidated automatically after running for X secs. No need to call ClearAndInvalidateTimerByHandle unless it is not running yet or it is in loop.

Here’s an example

Example 1

SetTimer 3 sec
IsActive? True
IsValid? True
After 4 secs
IsActive? False (Why? Timer has executed already, it is now invalid)
IsValid? Unsure (could be True or False)
(No need to call ClearAndInvalidateTimerByHandle here)

Example 2

SetTimer 3 sec
IsActive? True
IsValid? True
After 2 secs
IsActive? True
IsValid? True
ClearAndInvalidateTimerByHandle
IsActive? False (Why? Timer has been invalidated it is now invalid)
IsValid? Unsure (could be True or False)

In summary, never use IsValid for checking the active status of a timer. Use IsTimerActiveByHandle instead.