I’m probably just misusing animation montages because I love how they work with the notifies as a kind of callback etc. So, I love the idea of using them to do things like setting when a character can attack etc.
The problem I’m seeing is that if another montage is played before one gets to a notify, that notify isn’t hit.
So, for example if I set a canAttack boolean to false when an attack montage starts and then I intend to use a notify toward the end of the montage to set it back to true, but another montage (say gotHit) plays before that notify position, the character can end up in a state where canAttack is forever false.
Is there a proper mechanism for handling this, or do we just build around it? My solution at the moment is to fire a function on a timer after the animation montage node so that canAttack is set back to true as long as no montage is playing, but that is messy and seems hacky, so I can’t help think there is a mechanic I’m not aware of for handling this kind of thing.
I found a solution, thanks to https://answers.unrealengine.com/que…ion-event.html if I’m using a PlayMontage node from an animation blueprint. It has a nice little OnInterrupt exec pin. If I’m using a PlayAnimMontage from a character blueprint, I don’t have that option though, so I would still like to know if there is a proper way to handle this.
The PlayAnimMontage returns 0 if it failed to play, but doesn’t block until it finishes, so as long as it starts the value returned appears to be the length of the animation.
The Animation Montage Notifies are what I’m using, but I’m a little slow, so I’m not positive I follow your solution.
I think you’re talking about something similar to what I was doing, where I basically just called a function on a timer after I start the montage and make sure that nothing was left in limbo.
If so, it does work fine, and I don’t see where it would be a performance issue when it’s just setting a variable or two, and it isn’t a lot of spaghetti clutter or anything. The only problem I see with it is that it can create another problem, where this delayed function must be aware if say another attack montage has started and the canAttack variable actually doesn’t need to be reset. Again doable, but at that point the blueprint starts to get a little more cluttered and the solution starts to feel a little more hacky.
What I expected to see was something like a tickbox in the details panel for a Notify. Something like “Differed Call” or similar that would mark the Notify as one that needs to happen even if the animation doesn’t get to it. That being said, it would be basically the same thing we’re talking about under the hood, I’m sure.
What I have started doing for now is using only the PlayMontage nodes that are available to AnimInstances (Animation Blueprints) so that I can make use of its OnInterupted event. It means I need to call out to the Animation Instance to perform attacks etc, but it honestly feels more right anyway to have all of the animation code in the AnimationBP.
1st situation. Yes an obvious issue. You just wouldn’t use it in case of combos or things you need to rely on.
2nd situation. What you are calling a deferred call, well, its really just the first thing, but instead of triggering the Off switch you are triggering the function you want executed regardless of interrupts.
3rd, actually the animation graph should be very minimal/empty.
the animations in it should play just based on variables, without any logic.
So make use of them anyway. On BeginPlay in character memorize the ABP off a cast. Then use the stored variable to call the same montage function offering interrupts.
Thanks for the input. Now that you’ve mentioned it, I see that having any long running code in the ABP is a thing I should avoid.
I’m just going to re-think how I’m doing this enemy setup. It’s a pretty simple combo, so I will probably just have it play though all 4 attacks in a single montage as long as, say a boolean inAttackLoop is true, and I can just toggle that from the character bp via a reference to the ABP.
Any time what I’m doing seems problematic, I suspect that I’m just not using the methods that I should be.
I guess only know about a small part of UE at this point, so I try to solve everything with those few tools I’m aware of. Give a caveman a stick and a problem, and he’ll try to solve the problem with the stick.