Humanoid.StateChanged is inconsistent and inaccurate when listening to a player on other clients

When listening to a player’s Humanoid on a client who is the player, StateChanged works perfectly fine. The following are printed consistently every time when jumping:

-- Jump 1
Enum.HumanoidStateType.Jumping
Enum.HumanoidStateType.Freefall
Enum.HumanoidStateType.Landed
Enum.HumanoidStateType.Running

-- Jump 2
Enum.HumanoidStateType.Jumping
Enum.HumanoidStateType.Freefall
Enum.HumanoidStateType.Landed
Enum.HumanoidStateType.Running

-- Jump 3
Enum.HumanoidStateType.Jumping
Enum.HumanoidStateType.Freefall
Enum.HumanoidStateType.Landed
Enum.HumanoidStateType.Running

Meanwhile, when listening to a player’s Humanoid on clients who are not the player, StateChanged fires inconsistently. Sometimes Jumping doesn’t fire, sometimes Landed doesn’t fire, sometimes they both don’t fire, sometimes they all fire, etc:

-- Jump 1
Enum.HumanoidStateType.Jumping
Enum.HumanoidStateType.Landed

-- Jump 2
Enum.HumanoidStateType.Jumping
Enum.HumanoidStateType.Freefall
Enum.HumanoidStateType.Landed
Enum.HumanoidStateType.Running

-- Jump 3
Enum.HumanoidStateType.Jumping
Enum.HumanoidStateType.Freefall
Enum.HumanoidStateType.Running

(localPlayer ~= player on left, localPlayer == player on right)

targetPlayerHumanoid.StateChanged:Connect(function(old, new)
	print("old, new = ", old, new)
	if new == Enum.HumanoidStateType.Jumping then
		print("Target jumped!")
	elseif old == Enum.HumanoidStateType.Landed or (old == Enum.HumanoidStateType.Freefall and new ~= Enum.HumanoidStateType.Landed) then
		print("Target jump ended!")
	end
end)

This is incredibly frustrating and makes listening to StateChanged (e.g. to detect jumping) on other clients completely impossible to do reliably.

The developer API also specifically states to use StateChanged to detect jump landings, and as far as I’m aware this is impossible to do reliably without additional complexities such as raycasting.

This bug report is also similar to an unresolved one from three years ago: Humanoid.StateChanged for jumping and Humanoid.Jumping do not fire consistently

14 Likes

While this is not a fix to the exact problem, as a workaround to this you could move away from .StateChanged, as detecting this on a per player basis can be quite needlessly expensive.

In my testing, explicity listening to states such as .Jumping and .FreeFalling seem to do exactly what you’re looking for:

Humanoid.FreeFalling:Connect(function(IsFalling)
    if IsFalling then
        print("falling")
    else
        print("landed")
    end
end)

Humanoid.Jumping:Connect(function(IsJumping)
    if IsJumping then
        print("jumping")
    end
end)

Humanoid events like FreeFalling, Jumping, etc appear to have the exact same results - they too fire inconsistently, never, etc on clients when listening to player humanoids not belonging to them. I imagine they’re called by something similar/identical to StateChanged underneath the hood.

2 Likes

Interesting, I wonder how on earth the roblox Animate / Sound scripts handle this then :thinking: last i recall they use those events.

1 Like

In general property replication only guarantees eventual consistency, but may (will) drop intermediate values between replicator steps where that changed event is flushed from the queue.

The behavior you’re seeing is intentional. It reduces network traffic and puts a cap on how frequently state change events are transmitted.

Even though Humanoid state replication currently technically goes through the physics sender instead of the normal property replicator, the same guarantees apply. Intermediate states between replication steps will be dropped. The server and other clients that are not authoritatively simulating the humanoid will see a lossy set of state changes.

If you do need other clients to get guaranteed notifications of every jump event you should implement them with RemoteEvents, which do not use the same coalescing as properties.

Annoying, but for most games that do not have anything special happening on jump the bandwidth savings is a desirable thing.

17 Likes

This post is quite old, but I will still reply to it, the events free falling and jumping are quite consistent and I never had any problems with them, maybe 2 years ago aka the time you guys were talking about this it wasn’t working, but now in 2023 it works perfectly fine.

2 Likes

I’ve had this exact same problem and it’s driving me insane, I’m glad I’m not the only one and I’m assuming the only way to fix it is by creating the state detection myself which as you said is a takes extra complexities.

EDIT: I’ve created a system that works quite well to detect jumping and landing, it listens to differences in vertical velocity of a certain magnitude and fires states accordingly. For example when you land you quickly go from a negative velocity to a almost still velocity and so you can listen for that difference and fire the land function accordingly. There’s probably a few flaws with this system but its better than using raycasting and its independent of the Roblox movement handler. It’s still quite inconsistent because networked physics to clients are also inconsistent just like the state changes but its a lot more usable.

1 Like

I’m curious, what exactly is the mechanic or system which this is being used for?

I’m networking custom character movement sounds of other players to be handled entirely on the client so that they can be manipulated locally at the clients request, which is why I’m not just playing them on the server side to be networked by Roblox. I’m quite positive Roblox also does this with the default character sounds but because of the topic of this post they’re probably also inconsistent. I could use remote events to network all the state changes from the consistent source that is each client to every other source client like the staff member suggests but that would be horribly expensive on the server for no reason so instead I am just handling them on the client by monitoring every other existing character. From my understand this is also exactly what the original poster is doing. This is probably expensive on the client as well but I’d rather keep the server as fast as I can. Anywho the fact that other players state changes aren’t consistent, the topic of this post, makes it so, as I mentioned, I gotta make my own state detector. The system mentioned is the way I am detecting jumping and landing for jumping and landing sounds.

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