Deprecating LoadAnimation on Humanoid and AnimationController

Some of you have already noticed that Humanoid:LoadAnimation, AnimationController:LoadAnimation, and all the other animation related APIs on Humanoid and AnimationController were marked deprecated. This wasn’t an accident!

Of course these deprecated methods are not going away; we can only rarely remove deprecated functionality without breaking games. However, we strongly discourage their use.

Using these deprecated methods as intended can easily lead to broken animation replication. It’s a trap! We see this happen to a lot of developers, and it’s usually difficult to diagnose when it happens. There are easy alternatives that prevent this from happening.

Recommended Alternative

Use Animator directly instead. Cut out the middle man!

You should always create the Animator on the server. This can be done with Instance.new("Animator"), or by just adding them as children of your Humanoid or AnimationController at edit time in Studio.

All replication of animations is handled through the Animator instance. If the server doesn’t know about the Animator that you are using on the client, animations will not replicate.

Client-side animation scripts should use WaitForChild("Animator") to get a reference to the server created Animator. The default Animate script has not been updated to follow this yet, but we’ll update it as soon as we can!

Reasons We’re Deprecating Them

The reason we did this was documented on the devhub previously:

Both Humanoid:LoadAnimation and AnimationController:LoadAnimation will create an Animator if one does not already exist. When calling LoadAnimation from LocalScripts you need to be careful to wait for the Animator to replicate from the server before calling LoadAnimation if you want character animations to replicate. You can do this with WaitForChild("Animator").

If you call these deprecated LoadAnimation methods on a client before the Animator exists on the server, LoadAnimation will create an Animator that only exists on the client, This Animator will be unable to replicate the state of playing animations as expected.

These methods are only thin proxies that redirect calls to the Animator instance anyway. The Animator itself does all the actual animation work. These proxy methods only exist for historical reasons, from before the animation system could be used without Humanoids. Those were dark times.

The only remaining reason to use an AnimationController is to have another parent for the Animator. The Animator searches for animatable joints and Bones in descendants of its parent’s parent. This behavior is subject to change subtly in the future to eliminate this requirement for this intermediate parent between the Animator and the Model itself. We plan to change this to check the type of the Animator’s parent, and if it is a Humanoid or AnimationController search the descendants of the controller’s parent, otherwise searching descendants of the Animator’s parent. You must continue to have an AnimationController or Humanoid as a parent of the Animator in the meantime.

We know some developers deliberately exploit desyncronized Animators. You know who you are. Don’t do this unless you really know what you’re doing. We don’t encourage this because it means you need to re-invent animation replication entirely. This is a lot of work to maintain, and usually a bad use of your time. In the future we still want to more directly address the use cases that causes people to do this intentionally.

217 Likes

As always, removing unnecessary and arguably terrible ways to accomplish the same goal. I agree with this decision.

50 Likes

I see nothing really wrong with doing this, it was an outdated way and pushing a cleaner way is always good. :+1:

9 Likes

Thank you for giving out a public announcement on LoadAnimation and it’s final days for animations on the platform, will make sure to take notes and consider using the new alternative for this. :slight_smile:

By the way, can we get a global message that LoadAnimation and AnimationController are being deprecated like I’ve seen in the past with some other functions like LoadLibrary that had to be deprecated? I would be happy and developers would be noted that this function and Instance for animations and have the alternative to use instead.

Good decision, although it would be hard to change a ton of my scripts. :sweat_smile:

14 Likes

You don’t! Keep using them.

Think of AnimationControllers as special Folders for your Animator. They add zero value, but you still need to have one for now for weird historical reasons.

In your scripts it’s preferable to skip right over the AnimationController and go grab a reference to the Animator itself. You shouldn’t need to change anything else in your scripts. API is the same. AnimationController is a dumb proxy.

29 Likes

I never expected this news…
Will any games with this function still be able to run with this feature being deprecated?

6 Likes

Uh… Excuse me… i don’t understand scripting!
And this is why i hate this update

I have 2 AnimationControllers (wich i took from the library, because i don’t understand scripting), one for the server (wich is a script) and another one for the client (as a LocalScript)

I use this pair in every custom rig that i make, i NEED to run animations in them!

@ContextLost What i do?

7 Likes

Yes*, deprecating just means its recommended to no longer use it. The funcationality of it will still be there.

9 Likes

Yes, they will, it says it on the announcement

6 Likes

Could have at least gave us a heads up… I just finished working on my AnimationService module :pensive:


@ContextLost what happens if we create the Animator on the ClientSide only?

Can we expect to have more documentation for Animations in general?

The lack of documentation is a reason why we have so many unexpected behaviors and problems that leads to frustration and wasted resources.

14 Likes

Considering an Animator is required for humanoid:LoadAnimation and animationController:LoadAnimation anyway, will the Animate script account for this? Will a server script be added to Characters by default that instantiates an Animator? Seems like a pain to me to have to add Animators myself n CharacterAdded in each game I make.

8 Likes

As long as it doesn’t spam the output with a warning like “This API is deprecated” then this sounds like a great change going forward!

This is because we likely won’t touch our current stuff (that isn’t broken) but for future projects this is how we’ll do it.

18 Likes

Great change for moving forward! However, I just recently finished my new animation system for my game so I don’t think I’ll be changing that anytime soon.

Just wondering, will you be making a detailed developer hub post on animations in general? I feel like another user above me asked this but I think it’s a crucial point to cover.

Also, when can we expect for the new changes with AnimationControllers and Humanoid to take effect?

4 Likes

I’m glad that changes like this are being made to help developers spend less time getting frustrated about confusing, unknown issues.
I think that Roblox would be able to go further if you guys create articles frequently which are also extremely helpful. Perhaps conducting more surveys about what developers value most will help with this, should you guys do this.

4 Likes

I don’t think there are any changes to Humanoids or AnimationControllers, they’ve just deprecated the LoadAnimation API for both of them.

2 Likes

They are certainly changing it fundamentally.

There are changes to the entire structure as a whole. Just wondering when we can expect to switch from the old methods of using AnimationControllers and Humanoids.

4 Likes

Deprecated means usable but less uhh practical if i have to say. But ah well. im going to rewrite whole script. I have to agree considering if we have to load so many animation especially in heavy game

3 Likes

How does the Animator object function with streaming? What if, for example, an animation loads on the client before the full rig replicates (since BaseParts can stream in after the Animator object). Would this lead to some limbs not being animated, or will newly introduced limbs be immediately animated?

This is one of the biggest reasons I haven’t made certain animations client-side in my game yet, since my game uses streaming. The interaction with streaming is very buggy and hard to test empirically because of its inconsistency.

5 Likes

What method should I use to load the animation instead now?

1 Like

A lot of people seem confused about deprecation in this thread or whether this changes any existing behavior.

The Animator object was already doing the heavy lifting of the animation system. The LoadAnimation functions that were deprecated are not going away and still work the same as they always have, it’s just that their use is not recommended going forward. Internally, they have always aliased to the underlying Animator object, creating it if it didn’t exist, and directing the call to that object instead.

The key issue here is synchronization between the client and server when it creates the Animator object with LoadAnimation on the Humanoid/AnimationController classes.

If a call is made to LoadAnimation on the server and client at the same time, both ends would try to create their own Animator objects. This causes replication to fail because the client would send replication through the Animator it created, while the server would expect to be receiving events from the Animator it created.

The solution is simple. If you have the Animator object pre-made on the server before the client ever calls LoadAnimation, this won’t ever be a problem and you can continue to use the deprecated functions as normal.

This deprecation is ultimately focused on preventing this client-server desync pattern from accidentally happening in the first place. By making the client wait for an Animator to be made on the server in the first place, and using it Animator:LoadAnimation instead, the problem will cease to occur.

31 Likes