New Event: AnimationTrack.Ended

Hi Developers,

We’re excited to release AnimationTrack.Ended - a new event on the AnimationTrack instance.

Currently, AnimationTrack.Stopped event work as intended. “Stopped” fires the moment that AnimationTrack decides to “wind down”, e.g. after calling AnimationTrack:Stop. Depending on the length of the fadeTime argument, the animation will continue to move its subject until the subject returns to a neutral pose.

Without an API change, there is no way to know for sure that an AnimationTrack is finished affecting the world. We want creators to be able to detect that as well when an AnimationTrack is finished moving its subject.

That’s where AnimationTrack.Ended comes in.

Solution

When AnimationTrack.Ended fires, the AnimationTrack is “completely done” and will no longer be moving anything at all.

This is useful for cases where you want to perform an action (e.g. destroying the animation track) only when it is finished affecting the world.

Sample code:

– I want the animation to fade out over 5 seconds. Then, and only then, I want to clean it up.
animationTrack.Stopped:Connect(function()
   – The animation track is still moving the subject!
   – Don’t clean things up here.
   print("Stopped Event fired")
end)

animationTrack.Ended:Connect(function()
– The animation track is completely finished moving things.
– Now we can safely clean things up.
   print("Ended Event fired")
   animationTrack:Destroy()
   animationTrack = nil
end

print("Calling animationTrack:Stop")
animationTrack:Stop(5)

The debug would be:

Calling animationTrack:Stop
Stopped Event fired
Ended Event fired

(Note: There’s a five second delay between printing second and third lines).

Alternate Solutions without using AnimationTrack.Ended

You could use existing API to achieve something like this:

animationTrack.Stopped:Connect(function()
   task.wait(5)
   animationTrack:Destroy()
   animationTrack = nil
end)
animationTrack:Stop(5)

But:

  • Using task.wait is generally a code smell, to be avoided. You don’t need it with Ended event.

  • Depending on the complexity of your code, at the point you handle the “Stopped” event you might not know the fadeOut param that was passed into Stop.

  • There are no guarantees that the fadeOut will take exactly time passed in. You might wind up a few frames ahead of or behind the actual time when the AnimationTrack stopped affecting the world. The “Ended” event is guaranteed to be precise.


Please share your feedback down below and let us know if you have any questions

Thank you.

178 Likes

This topic was automatically opened after 10 minutes.

Looks good, but just to clarify, does this also fire if the AnimationTrack is not looped and finishes on its own? And if we don’t delete the track, does it also fire again if the track is stopped again?

5 Likes

Very happy to see this implemented; we no longer need hacky solutions to solve simple problems!

On the same topic, will there ever be functionality to allow animations to be “additive”? In other words, when could we expect animations to have the ability to be added to each other, rather than blended?

An example of additive animation would look like this:

I remember when I used to work for another studio that wanted me to make an entire animation engine for the sole purpose of implementing additive animation because it’s that powerful. It would be a time-saver for sure if this was native to Roblox!

Update: I made this a feature request. Check it out here: Allow animations to be additive

62 Likes

Isn’t this already a thing? You could just make your animation not affect certain Motor6Ds/Bones. Then when playing the animation, you can set the weight of it, so it gives it like a mixed/added feel to it. I don’t know if this and additive animations are the same thing, but this is what I do to replicate a half version of it.

4 Likes

So cool to bad I don’t know how to code that good

6 Likes

You should make a feature request because I doubt that Roblox will even read your request here. But yeah, that would be a nice addition to the engine.

2 Likes

It’s not really true additive animation since it still blends the animations together instead of adding onto the previous transform of the animation, but since that’s your intended use case there’s no complaints there.

3 Likes

You can do this by using different priorities on the animations as well as authoring the higher priority animation only animate certain limbs.

1 Like

Amazing! Quick question though, is the issue of AnimationTrack.Looped not replicating fixed? I haven’t tested it myself but since that post seems to remain with no solution gives me the sense that no.

But can a staff member confirm is fixed please?

7 Likes

Fantastic! I look forward to using this once I need to, which is inevitable. It’s always nice to see functionality expanded upon.

May I mention, you can easily implement the cleaning process with the Animator.AnimationPlayed event.

Animator.AnimationPlayed:Connect(function(animationTrack)
   animationTrack.Ended:Connect(function()
      animationTrack:Destroy()
   end)
end)
2 Likes

Nice one! Now I ran into an issue with .Stopped before, now I can delete my old whacky solution.

1 Like

I have once tried this event before, but it does not work. It`s grateful to see the progress of animation controlletion. Great Work Roblox!

I always enjoy seeing improvements to the animation system.

Are there any plans to allow for scaling of animation positions, during runtime, or during the track loading?

1 Like

No. Animation blending and animation addition are not the same thing.

1 Like

That is not additive animation, that is simply blending.

1 Like

The two animations will only blend together if they have the same priority. What you want to do can easily be done with animation priorities.

The default “hold tool” animation is an example of this.

Does this fire inbetween loops if a track is looped? or just on non-looped tracks? Please update w/ information

1 Like

What? I thought task.wait() was better to use than wait(). Why is it a code smell?

3 Likes