Animation Replication Issues using Animation Editor

I am using an Animation Controller to animate custom models that are attached to the player and that the player controls. The AnimationController and all of the Animation instances are created server-side, and the input by the user is done locally and sent to play the animations on the server with Remote Events.

However, for a long time there have been subtle glitches with the animations causing some parts of the model to not move properly. On the player’s client, their model looks normal, but on the server, only half of their model is moving the right way. All of the parts in the custom model are connected with Motor6D and all connect to the PrimaryPart of the model.

I’ve read on the Wiki that using AnimationController or Humanoid to animate a locally controlled model might cause some undesired effects:

If an AnimationController is created on the server, its animations should be loaded and played on the server unless a player has been assigned network ownership of the Model 's root part using BasePart:SetNetworkOwner . If an AnimationController is created on the client it should be animated by the client.

Although it is not recommended, if a developer wishes to play animations on a locally controlled Model from the server they can use the Animator object. -ROBLOX WIKI

So, after reading this, this is what I’ve done to try to solve the issue:

  1. I tried to load the Controller and the Animations only locally, but then the problem was only the player could see the animation from the client, and no one else server-wide could see it.

  2. I also tried to set the NetworkOwner of the primary part of the custom model to the server. The output doesn’t give any sort of error, but the animations simply stop working altogether, client and server. The custom character’s NetworkOwner is the player’s client by default since it’s Parented to the player’s character.

This is the script I’m currently using that’s causing these issues:

LOCAL SCRIPT (located in PlayerGui):

local actions = (morph):WaitForChild("Actions")
local FireWalk = actions:WaitForChild("Walk")

Player.Character.Humanoid.Running:connect(function(speed)
    if speed > 3 and not walking then
		walking = true
		FireWalk:FireServer(tween) --Fires Remote Event to start the Walking animation
    elseif speed < 3 and walking then
		walking = false
		FireWalkStop:FireServer(tween) --Fires Remote Event to stop the walking animation
    end
end)

SERVER SCRIPT (located on the Player’s custom character model):

local actions = script.Parent:WaitForChild("Actions")
local FireWalk = actions:WaitForChild("Walk")

FireWalk.OnServerEvent:Connect(function(player,tween)
	local Walk = script.Parent.AnimationController.Walk
	local WalkTrack = script.Parent.AnimationController:LoadAnimation(Walk)
		WalkTrack:Play(tween/2)
end)

FireWalkStop.OnServerEvent:Connect(function(player,tween)
	local AnimCont = script.Parent.AnimationController
	for _,WalkTrack in pairs(AnimCont:GetPlayingAnimationTracks()) do
		if WalkTrack.Animation == script.Parent.AnimationController.Walk then
		WalkTrack:Stop(tween/2)
		end
	end
end)

This script produces no error and works fine, but sometimes there are subtle glitches in the character models’ animations, and sometimes they are very noticeable.

I also read this article: Animator | Documentation - Roblox Creator Hub , but I am having a hard time understanding what it means. It’s suggesting that the Animator instance automatically replicates client-controlled models to the server, but it was not the case for me since in my previous attempt to load the animations locally, only the client could see it. If someone could explain this to me it would be very helpful!!!

Playing Animations through Humanoid:LoadAnimation allows animations to replicate to the server meaning other clients can see the animations being played on your character. (This is because you have network ownership of your player)

You can load animations and play them like so:

local Animation = Instance.new('Animation')
Animation.AnimationId = 'rbxassetid://ID_HERE'

local AnimationTrack = Humanoid:LoadAnimation(Animation)
AnimationTrack:Play()

If you want to use an Animation instance directly rather than loading through an Id, just remove the first two lines and do Humanoid:LoadAnimation(Instance).

I am not using a Humanoid to animate my model. It’s a custom built model that I am using AnimationController to animate since it is not a human. The issue isn’t that the animation doesn’t play. The animations plays, and other people can see it, but some parts of the model glitch and bug out.

Oh, on mobile so I didn’t see the second chunk of code. I’m not sure what you can do to animate it correctly then, since I don’t have experience with animating non-Humanoid models. Apologies.

I’ve tried a few more possible solutions but none of them seemed to work:

  1. I tried to load the AnimationController and all of the Animation instances and ID’s completely locally and used AnimationController:LoadAnimation() locally, but only the player’s client could see the animation and no one else, which is what I expected. The wiki states that loading animations with the AnimationController should work locally, but in testing, it does not replicate to others.

  2. I tried to load animations using Animator:LoadAnimation() instead of AnimationController:LoadAnimation() because of the wiki article that states that using the Animator to load the Animation will properly replicate locally controlled models to the server. The animation loaded, and both the client and other players could see the animation, but it was doing the same thing as before and pieces of the animation were glitched out and not moving. (As in, half of the model was in the T-pose, and the other half of the model was animating regularly)

This has been going on since around November and I haven’t found a solution to this yet. Any help or advice or input is appreciated!!!

Here are some examples of what I’ve been experiencing. The AnimationController and all of the Animation ID’s are created by the server and LoadAnimation() is executed by the server as well.

This is an example of what it looks client-side. It looks normal, this is what the animation is supposed to look like.
example

This is an example of what it looks like on the server. Half of the animation plays normally, like the head and tail, but the wings and legs are still stuck in a T-pose:
help

This produces no error in the output and the parts that get stuck are usually random.
It appears to be random when it works and when it doesn’t, too. Sometimes, the server plays the animations as they are supposed to be played, and sometimes they get T-posed like this.

Anyone with similar experience or experience animating models with AnimationController using local input?

Update: Here are some more things I tried.

I tried not using the AnimationController alltogether and loaded animations in with Humanoid:LoadAnimation() instead. Humanoid and Animations loaded in by the server, and Humanoid:LoadAnimation executed by the server produced the same results where half of the model is animated and the other half is not.

I’m attempting to play only 1 animation, and its priority is “Idle”

I also tried loading in Humanoid and the Animations locally and using Humanoid:LoadAnimation() in a local script. I read on the wiki that it should work either way, but doing it locally prevents other players from seeing the Animations at all.

I checked the Network Owner of the model and it automatically defaults to the player since it’s welded to the HumanoidRootPart.

I tried to set the NetworkOwner to nil so the model would be owned by the server, but this makes it so ONLY other players can see the animations, but not the client.

I’m completely stuck here :frowning:

After a week of trying to fix this, I have still not come to a conclusion. Here are a few more things I tried:

I tried parenting the local script with the animation function in it to both the player’s character and the model itself. I also tried keeping the local script inside of PlayerGui. I also tried cloning the model itself from ReplicatedStorage instead of ServerScriptService where it has been originally.

I’ve been told by several sources that I should load player controlled animations using local scripts, but whenever I use local scripts to create,load and play the animations, they always only play client-side. The only time the character animations are played server-side is when I use server scripts, but doing that causes the strange glitches where parts of the model stay frozen while some parts don’t. The model’s network owner by default is the player since it is welded to the HumanoidRootPart. I also tested and confirmed this with GetNetworkOwner, so playing animations locally in theory SHOULD replicate. Setting the NetworkOwner to nil makes it so the animations don’t play at all.

I know there has to be something I’m missing, any help is still very appreciated!!!

Can you replicate the problem in a simple Roblox file and upload it? That would make it a lot easier to understand exactly what is going on and try to fix it.

1 Like

examplechick.rbxm (25.8 KB)

This is an example of one of the models the glitch is affecting. The glitch is happening to all of the animated models I use in the game.

The model is cloned from ServerScriptService and attached to the player’s Root Part on a Server Script in ServerScriptService through a Remote Event after a button is pressed. Then, a script that controls the animations is cloned from a folder in ServerScriptService and placed inside of the morph and then its enabled. Then, the animation controller and the animations are created and loaded in on the server script.

resize.OnServerEvent:Connect(function(player)
	if player.Character:findFirstChild(morph) == nil then
		repeat wait() until script.Parent:findFirstChild(morph)
		local g = script.Parent:findFirstChild(morph):Clone()
		g.Parent = player.Character
			local Y = Instance.new("Motor6D")
			Y.Part0 = player.Character.HumanoidRootPart
			Y.Part1 = g.Root
			Y.C0 = CFrame.new(0, 0, 0)
			Y.Parent = Y.Part0
		g.Root.Anchored = false		
	end
     local birdanimate = script.Parent.Animations.Animation:Clone()
     birdanimate.Parent = player.Character:WaitForChild(morph)
     birdanimate.Disabled = false

repeat wait() until player.Character:FindFirstChild(morph)
local AnimCont = Instance.new("AnimationController")
	AnimCont.Parent = player.Character:WaitForChild(morph)
local Fly = Instance.new("Animation")
	Fly.Parent = AnimCont
	Fly.Name = "Fly"
	Fly.AnimationId = "rbxassetid://2954798478" -- This goes on for all of the animations
        ...
        ...
end)

Everything is done server-side, and this is the only method that works when it comes to other players being able to see the animations. I’ve tried making and playing the animations on local scripts instead of server scripts but it does not work.

I tried making the models Massless and not Massless, and both don’t seem to change the glitch at all.

From what I’ve noticed, the only animations that work are animations that were loaded before the player joined the game. So for example, when a player joins, the animations of everyone already online work normally. The glitch happens when other players join AFTER the player joins the game. I noticed that this is the case 100% of the time.

Here is an example. My friend loaded her model after I had already joined game and only half of her animations are playing. On their client, they see themselves as animating normally. (Also this isnt the only model its affecting. I’m only using this as an example because its the easiest one to see)

Hmm… My theory is that the idle animation is played before the player joins the game. Once he joins, the idle animation is possibly not replicated and therefore does not appear properly for that client. The solution if this is the case would be to either replay the animation on the server, or fire a RemoteEvent to the joining client to play the animation.

You may have to set it up such that all animations are played client-side, and the server simply instructs the clients when to play the animations. This would also make the user experience for the players a bit better, as they could see their morph’s animations being played instantly (no latency).

1 Like

You may have to set it up such that all animations are played client-side, and the server simply instructs the clients when to play the animations.

This is the problem, this is what I’ve been trying to do, actually. When I set up the animations to play client side, the animations end up not playing at all. But I feel like I’m setting it up wrong, somehow. What would be the best method to play animations client-side using AnimationController?

1 Like

I’m guessing this is your issue:

Should I load an Animation on the client or server?

In order for AnimationTrack s to replicate correctly, it’s important to know when they should be loaded on the client (via a LocalScript ) or on the server (via a Script ). If an AnimationController is created on the server, its animations should be loaded and played on the server unless a player has been assigned network ownership of the Model 's root part using BasePart:SetNetworkOwner . If an AnimationController is created on the client it should be animated by the client.

I saw that you mentioned this in your original post, but I don’t know if you tried to manually set the network owner to that client.

1 Like

When the model welds to the character, it automatically defaults to have the network owner be the client. After I read this article, I made sure to only load/animate the animations using a server script, since the animation controller is created using a server script. Because this method is the one that causes the glitch, I redid the script to have the animation controller be created and loaded ONLY on the client with local scripts (and :LoadAnimation() be called with a local script as well), and this is what makes it not work at all - By this I mean, other players cannot see the animation at all. It would make sense to only try to access the animation controller with a server script if it was created on the server and vice versa.

Lately I’ve been trying to crack down on things that are out of the box that I might not have thought about before, like maybe the model being stored in the ServerScriptService might be the problem? Or maybe I should put an animation controller instance inside the model instead of creating the instance with a script?

I am pretty desperate at this point lol because i’ve been trying to fix this problem since early november when it started. (I’ll also add, the glitch started happening the same week Rthro came out, but im not sure if that has anything to do with it. It might be just a coincidence, or a change to how animations work)

When you create everything on the server, do you also explicitly set the network owner of the morph to the server? Otherwise, it will most likely automatically assign ownership to the client, which could possibly cause issues. I know when I was creating NPCs for my game I needed to manually set the network owner of the NPC to the server, otherwise the NPCs had some various issues involving animations.

In other words, if you are going to animate the morph from the server, you need to make sure (through SetNetworkOwner()) that the server has network ownership.

When you create everything on the server, do you also explicitly set the network owner of the morph to the server?

No i don’t, the model is automatically assigned to the client. I don’t touch the Network Owner at all.

In other words, if you are going to animate the morph from the server, you need to make sure (through SetNetworkOwner() ) that the server has network ownership.

I’ve already done this in a post I made a few weeks ago to this thread. The outcome was that the animations stopped playing completely for the client and only played for other people. So, the client would see themselves t-posting, but everyone else sees them animating normally.

I was trying things out again today and one really weird thing I noticed just today was that, when a part from the workspace is welded to a part in the character model that is having the animation glitch, suddenly the glitch stops and the animations work again. (This happens when characters pick up objects in my game.) I tested this over and over and it works every time. What could this mean??

Maybe it causes some sort of under-the-hood refresh? That suggests this could be some sort of engine bug, but I’m not 100%.