UMG animation complete blueprint event

Is there any way in blueprints to be notified when an UMG animation sequence finish playing? Currently we’re using the delay node, but when someone modifies the animation length, the delay needs to be updated as well, which is very error-prone.

1 Like

Bump this question. I also need this feature!

The solution I have used is to add a method to the UWidgetAnimation class to expose the duration of a given animation. You can then setup a delay of the right length. It isn’t ideal as requires you to be starting the event in the Event Graph (so you can use the delay). Hopefully at some point the UMG animation stuff will be a bit more feature complete… Anyway, here is the code for the duration:

Decleartion:

UFUNCTION(BlueprintCallable, Category = "Animation")
float GetAnimationDuration();

Implementation:

float UWidgetAnimation::GetAnimationDuration()
{
	if (MovieScene)
	{
		TRange<float> AnimationRange = MovieScene->GetTimeRange();
		return AnimationRange.GetUpperBoundValue() - AnimationRange.GetLowerBoundValue();
	}
	else
	{
		return 0.0f;
	}
}

When I get a min I’ll create a pull request. Unreal devs, is there a reason why the UWidgetAnimation is both MinimalAPI and not exposed as a BP type?

Works great! I needed a way check if an animation was completed from an external module and your example here was a lot of help.

If you don’t mind editing the engine though, I think you can avoid that dependency on the Delay node. In the UserWidget class, you can change how animation endings are handled. Just look for:

void OnAnimationFinishedPlaying(UUMGSequencePlayer& Player );

You can check which animation has been played through the Player variable and pass that to your own blueprint event or C++ Function to start executing your logic.

I’m trying to avoid making changes to the engine so I haven’t actually attempted this. Just something I was thinking about as I was writing up my code.

I kept hitting a wall trying to get a widget animation to play in reverse so I came back to my idea and it works! You actually can trigger your own event whenever your animation finishes without touching the engine. This method still has a requirement however, you need to change how you call PlayWidget(). I would recommend creating a blueprint function library so you can create a node to replace PlayWidget() completely as opposed to trying remember to add your event every time.

Alright, here’s an example of how I set up the event. Note that the first half of the function probably isn’t relevant to most of you guys.

void AMyActor::PlayWidgetAnimation(UWidgetAnimation *_animation)
{
	if (widgetComponent == nullptr)
		return;

	UUserWidget* widget = this->widgetComponent->GetUserWidgetObject();

	if (widget->IsValidLowLevelFast())
	{
        // Call PlayAnimation and let UE4 set up the basic animation stuff:
		widget->PlayAnimation(_animation);

     // Now I'm adding my own event to the widget, this is the most important line!:
		widget->ActiveSequencePlayers.Last()->OnSequenceFinishedPlaying().AddUObject(this, &AMyActor::OnAnimationComplete);
	}
}

UserWidgets keep track of their animations through the ActiveSequencePlayers array. After calling PlayAnimation a new animation gets added to this array. What we’re doing is adding another function to be called when OnSequenceFinishedPlaying is triggered on that animation.

And here’s a shell example of the function that would actually carry out your event logic:

void AMyActor::OnAnimationComplete(UUMGSequencePlayer& _player)
{
	// You can implement logic here that will be executed everytime an animation is completed

	// Using Delegates, you can create an event node in blueprint which will let you execute blueprint logic as well
	OnAnimationCompletionDelegate.Broadcast();
}

You can use an On Animation Finished event in your widget’s event graph, and check the event’s Widget Animation Reference against the animation you’re looking for.

1 Like