Animations not properly replicating to client

It’s been a while since I had to create a post to ask for help scripting. :sweat_smile:

I have been trying to get animations to work on a door model with an AnimationController. I have finally managed to figure it out, but for some reason the client-side animations are not being applied correctly. Allow me to demonstrate.

Server side (working)

Client side (broken)

I believe the issue is that the Opened animation track is not replicating to the client when played.
I would imagine the same issue would affect the Closed animation if the position of the door was not identical to the original position.

local Model = script.Parent
local Animator = Model.AnimationController.Animator

local openingTrack = Animator:LoadAnimation(Animator.Opening)
local openedTrack = Animator:LoadAnimation(Animator.Opened)
local closingTrack = Animator:LoadAnimation(Animator.Closing)
local closedTrack = Animator:LoadAnimation(Animator.Closed)
openedTrack.Looped = true
closedTrack.Looped = true

while true do
	openingTrack:Play(0)
	openedTrack:Play(0)
	openingTrack.Ended:Wait()
	task.wait(1)
	closedTrack:Play(0)
	openedTrack:Stop()
	closingTrack:Play(0)
	closingTrack.Ended:Wait()
	task.wait(1)
	openedTrack:Play(0)
	closedTrack:Stop()
end

image

1 Like

After some investigation it seems the issue is behaviour associated with the fact the OpenedTrack and ClosedTrack animations are looped.

For some reason this appears to prevent :Stop() from replicating to the client, causing the tracks to stop correctly on the server, but not the client.

1 Like

I had the same issue for my animation approach. I just switched my script to client side since it has its benefits like less lag, but yea it’s weird why it doesn’t stop animations. Don’t know why it’s the case.

1 Like

I’ve tried a few things and this seems to have had an impact.

By manually controlling the .Looped property, this animation issue resolves itself after the first loop. However, the first loop is remains broken.

local Model = script.Parent
local Animator = Model.AnimationController.Animator

local openingTrack = Animator:LoadAnimation(Animator.Opening)
local openedTrack = Animator:LoadAnimation(Animator.Opened)
local closingTrack = Animator:LoadAnimation(Animator.Closing)
local closedTrack = Animator:LoadAnimation(Animator.Closed)

while true do
	openedTrack.Looped = true
	openedTrack:Play(0)
	closedTrack.Looped = false
	closedTrack:Stop(0)
	openingTrack:Play(0)
	openingTrack.Stopped:Wait()
	task.wait(1)
	
	closedTrack.Looped = true
	closedTrack:Play(0)
	openedTrack.Looped = false
	openedTrack:Stop(0)
	closingTrack:Play(0)
	closingTrack.Stopped:Wait()
	task.wait(1)
end

Ok, think I’ve come to an acceptable compromise.

This code works every time an animation is played after the first.
The animation did not loop by default, so I fixed that.
Notably, this issue only arises once, the first time the animation is played on the server, regardless of if that animation is used elsewhere.
I’m guessing the .Looped property is replicated lazily after the first playback. Rather annoying but it works.

local Model = script.Parent
local Animator = Model.AnimationController.Animator

local openingTrack = Animator:LoadAnimation(Animator.Opening)
local openedTrack = Animator:LoadAnimation(Animator.Opened)
local closingTrack = Animator:LoadAnimation(Animator.Closing)
local closedTrack = Animator:LoadAnimation(Animator.Closed)

while true do
	openingTrack:Play(0)
	closedTrack:Stop(0)
	openedTrack:Play(0)
	openingTrack.Stopped:Wait()
	task.wait(1)
	
	closingTrack:Play(0)
	openedTrack:Stop(0)
	closedTrack:Play(0)
	closingTrack.Stopped:Wait()
	task.wait(1)
end

I’ve fully fixed the issue.
As I suspected, it’s a client issue.
Because assets are lazy loaded (i.e. they’re only downloaded when needed) the animation does not have .Looped set to true on the first pass of the animation.
However, if you manually preload the animations using ContentProvider:PreloadAsync() this issue is resolved.
Below you will find the local script I use for this.

local ContentProvider = game:GetService("ContentProvider")

local Animator = script.Parent

local Children = Animator:GetChildren()

ContentProvider:PreloadAsync(Children)

Animator.AnimationPlayed:Connect(function(track)
	if track.Animation.AnimationId ~= "rbxassetid://93803221032815" then return end
	print(track.Looped) -- false without `PreloadAsync` on first pass, true with it
end)

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.