Best way to change state on animation complete?

Let’s say I have an “isAttacking” boolean my animBP is monitoring. When the user presses the attack button, it changes isAttacking to true, causing the animBP’s state machine to play the attack animation. This boolean is also used to prevent the user from interrupting the attack with other button presses (jump, dodge, whatever).

What’s the best approach to have isAttacking set to false once the animation is complete?

So far I’ve done a few things that work but they all feel clunky and it’s making me wonder if I’m approaching the problem the wrong way. One option is to have a timer in the character BP, but then I have to manually set the time to match the animation.

Another approach is to have an attack montage call an animNotify that’s hooked up to a function that resets the character’s isAttacking to false. So far that the cleanest approach I’ve found but it still feels… weird.

Is there anything better/cleaner?

You can set an OnMontageEnded delegate for the Montage. The montage will call your function when it has finished playing the animation. You can then update any booleans. I do this in cpp with Montage_SetEndDelegate().

State machine Transitions have special nodes (only available in Transitions) that let you get the remaining time: Transition Rules | Unreal Engine Documentation (near the bottom)

You could use that in the transition rule to set the transition to isAttacking = False AND time remaining < 0.1 or some number you want.

Isn’t possible that this rule (cheking time remaining) fails if you have a low framerate?
I know this because I’m using Unreal in a eral slow machine (15 fps) and the transitions fail in some cases. I think that the problem is the threshold for time remaining.

No. But just use the “automatic rule” checkbox instead.
Which seems to work with fastpath.
Doing time remaining <= 0 isn’t fastpath compatible.
And the automatic rules seems to do the same exact job.

And I find out if I remove “Loop animation” the problem is solved also. That’s probably because it’s going to be a point in time when the animation time remaining reaches the zero point. It actually works if I use if =0 instead.