Inconsistent Animation Blending

Hello, All,

I’m working on the code for animating an NPC who generally just idles about but will wave at the player the first time they walk close. Currently, my code successfully does this, but with some problems.

Before getting into the issue, let me explain the backend a bit. The idle animations are all handled server-side and switch as intended via their controller. The wave is handled client-side (as it is not intended to replicate) by hooking into the Animator created by the server and running the animation in a LocalScript. About half of the time, this goes off without a hitch and the animation blends correctly with the idle animation, like this:


However, the other half of the time, the animation plays, but in doing so it snaps some of the unused joints into a straight position, like this:

Note: the animations are currently being looped for testing purposes.

How can I resolve this issue to achieve consistent results? Do I need to move all animating to the client end, or can I maintain this split structure?

1 Like

okay firstly yes it must be played on client using Humanoid.Animator:LoadAnimation()

second the unused joint happen when there is a keyframe in it if there isnt then it can be override with the default player animation or other animation that has a keyframe in the unused joint

I guess what’s confusing me is that the animations work entirely as intended some of the time (that is, like in the first clip) but not all of the time. This is how I have it set up (which I admittedly should have put in my initial post):

Server logic:

local idle_animations, idle_animations_count do
	local animator = Instance.new("Animator")
	animator.Parent = npc:FindFirstChildOfClass("Humanoid")
	--Script creates a server-side Animator.

	animator:LoadAnimation(script.IdleBase):Play()
	--Script runs the lowest-level, looping idle animation.
	
	idle_animations = script.IdleActives:GetChildren()
	idle_animations_count = #idle_animations
	for index,animation in ipairs(idle_animations) do
		local track = animator:LoadAnimation(animation)
		idle_animations[index] = track
	end
	--Script initializes all higher-level idle animations and stores them in an array.
end

--get_wait() defined elsewhere, returns a number.
while wait(get_wait()) do
	current_animation = idle_animations[ran(1,idle_animations_count)]
	current_animation:Play(0.1)
	current_animation.DidLoop:Wait()
	current_animation:Stop(0.1)
	--Script chooses a random higher-level animation that plays over top of the base.
	--Once the higher-level animation is stopped, the lower-level animation continues, unimpacted.
end

This script is successfully running the idle animations and replicating the results to clients without issues.

Client logic:

local wave do
	local animator = npc:FindFirstChildOfClass("Humanoid"):WaitForChild("Animator")
			
	local wave_animation = animator:LoadAnimation(script.Wave)
			
	function wave()
		wave_animation:Play(0.5)
		wave_animation:GetMarkerReachedSignal("WaveEnd"):Wait()
		wave_animation:Stop(0.5)
		--Unrelated logic omitted.
	end
end

When wave() is called, the animation does play, but it sometimes fails to blend correctly with the idle animations running on the server. The operative word here is “sometimes,” since I get both videoed results seemingly randomly by simply restarting the environment. It either works or it doesn’t, even if I make no changes between ending the last session and starting the next session.