How to fix jittery animation? (Un-consistent humanoid.Running(speed) argument)

Hello,

I have this script that animates the NPC depending on its humanoid.Running (speed) I’m having trouble figuring out on how do I properly detect movements.

humanoid.Running:Connect(function(speed)
	if speed >= monster:GetAttribute("RunSpeed") - 1 then
		if runAnim.IsPlaying == false then
			runAnim:Play(0.2, 3, 1)
		end
	elseif speed >= monster:GetAttribute("WalkSpeed") - 1 and speed < monster:GetAttribute("RunSpeed") - 1 then
		if walkAnim.IsPlaying == false then
			walkAnim:Play(0.2, 2, 2.4)
		end
	elseif speed >= 0.1 then
		if crawlAnim.IsPlaying == false then
			crawlAnim:Play(0.5, 1, 2.3)
		end
	elseif speed == 0 then
		idleAnim:Play(0.5, 1)
		crawlAnim:Stop(1)
		walkAnim:Stop(0.5)
		runAnim:Stop(0.5)
	end
end)

The issue is when testing it on studio it works perfectly fine transitioning to run, walk, crawl, idle animations. detecting proper speeds without humanoid.Running firing too often returning exact speeds. eg. RunSpeed, WalkSpeed of the humanoid.

And Testing it now on the live server
The humanoid.Running fires inconsistently or too many. When I set the humanoid walkspeed it’s speed from WalkSpeed = 8 to WalkSpeed = 20 it also fires and returns the in-betweens and also returns 0 Speed when even tho it’s moving…??

Assuming it’s moving on a straight line. setting its speed from 8 to 20 and printing its return argument.
eg.
speed 8 => 20
It prints 0, 8, 0, 9, 0, 10, 0, 11 ,12, 13 and so on…

On Studio:
it prints 8, 8.1, 20 which is fine. (Not returning 0 speed while moving)

hence when it returns 0… per frame it stops the runAnim and play’s the idle and the next frame it plays the runAnim again, giving its jittery motion per frame. It’s so hard to solve this issue because it’s not consistent from studio to live server.

Do note:
I tested it from using this
image
And also this
image
And works perfectly fine.

Humanoids tend to be a bit funky. I’d recommend leveraging the velocity attribute of parts to detect the speed of the NPC during runtime and adjust animation/animation speed accordingly.

You can use a similar paradigm here except you’d need to use RunService (iirc GetPropertyChangedSignal/Changed events don’t replicate for velocity). So basically at every render step check the NPC’s root part’s velocity and then run the same logic to adjust the animation.

2 Likes

Great idea, Would love to try it out.

Quick update it worked perfectly here’s the base concept I did for the others if ever someone comes across with it too. I rounded the speed so I get consistent non-decimal. and used AssemblyLinearVelocity magnitude to account for the whole NPC’s weight rather than the primary part only.

The Velocity is the same as the humanoid.Running return argument so I didn’t change much and just check below -1 to make sure I hit it since the Velocity doesn’t perfectly match the walk speed u prefer but super close enough to be accurate.

runService.Stepped:Connect(function()
	local speed = monster.PrimaryPart.AssemblyLinearVelocity.Magnitude
	speed = math.round(speed)
	if speed >= monster:GetAttribute("RunSpeed") - 1 then
		if runAnim.IsPlaying == false then
			runAnim:Play(0.2, 3, 1)
			crawlAnim:Stop(1)
			walkAnim:Stop(0.5)
			idleAnim:Stop(0.2)
		end
	elseif speed >= monster:GetAttribute("WalkSpeed") - 1 and speed < monster:GetAttribute("RunSpeed") - 1 then
		if walkAnim.IsPlaying == false then
			walkAnim:Play(0.2, 2, 2.4)
			runAnim:Stop(0.5)
			idleAnim:Stop(0.2)
		end
	elseif speed >= 0.1 then
		if crawlAnim.IsPlaying == false then
			crawlAnim:Play(0.5, 1, 2.3)
			walkAnim:Stop(0.5)
			runAnim:Stop(0.5)
			idleAnim:Stop(0.2)
		end
	elseif speed == 0 then
		if idleAnim.IsPlaying == false then
			idleAnim:Play(0.5, 1)
			crawlAnim:Stop(1)
			walkAnim:Stop(0.5)
			runAnim:Stop(0.5)
		end
	end
end)
1 Like

As you stated, changes in the values of physics based properties such as “Velocity”, like in this case, cannot be listened to (detected) through use of the .Changed event or :GetPropertyChangedSignal() instance method of the instance.

Yup can confirm it can’t. I tried this way but stick to the RunService instead.