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.
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:
AnimationController:LoadAnimationwill create an Animator if one does not already exist. When calling
LoadAnimationfrom LocalScripts you need to be careful to wait for the Animator to replicate from the server before calling
LoadAnimationif you want character animations to replicate. You can do this with
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.