Hello! I have recently been having difficulty with coming up with a method to accurately detect when a player hits the ground, from a jump or otherwise, on the server. I have played around with a couple of different methods, but each one seems to have its own drawbacks that prevent the desired behaviour.
Attempt 1: HumanoidStateType
My initial train of thought was to simply detect when the players humanoid changes state either FROM freefall, or TO landed. However, this proves unreliable as it sometimes fails to register when repeatedly jumping:
local stateConnection = char:WaitForChild("Humanoid").StateChanged:Connect(function(old,new)
if (old == Enum.HumanoidStateType.Freefall) or (new == Enum.HumanoidStateType.Landed)then
warn("LANDED")
end
end)
As the video shows, occasionaly this misses the landing. Doing this on the client does not give this issue. I assume itâs to do with the state not instantly replicating to the server?
Attempt 2: Raycasting
So I thought Iâd be able to fire a ray vertically down from the playerâs HumanoidRootPart, and if the distance between the rays hit and the HRP height (when standing) is less than a small margin then they must be grounded. However, the issue I had with this was that when repeatedly jumping, the HRP Y position doesnât reliably return to a low enough (standing) value on the server before the next jump begins, meaning that I canât determine if the player actually landed this way, not on the server at least.
Attempt 3: Part Direction
I then tried comparing the HRP Y position to its previous position in Heartbeat
. But I couldnât figure out how to do this. I can determine when the HRP changes direction, and from that determine when they jump. But to determine when they land, I need to check that a) the distance between the current and last position is less than some threshold value, and b) check that they were falling in the last heartbeat.
This was my attempt, but it is again very unreliable and sometimes fires multiple times during a jump, or not at all:
RunService.Heartbeat:Connect(function(DeltaTime)
local pos = player.Character.HumanoidRootPart.Position.Y
if math.abs(pos - lastYPos) > 0.2 then --if we have moved significantly since the last heartbeat
lastDir = math.sign(pos - lastYPos)
else
if lastDir == -1 then --if we were falling but now havent moved significantly, we landed
warn("Landed")
end
lastDir = 0
end
lastYPos = pos
end)
So, my question is how do I accurately and reliably determine, on the server, when a player hits the ground, even while repeatedly jumping? It seems like such a trivial issue, I am surely missing something obvious here! Or, since a playerâs movement is client driven, is it actually as safe to simply detect a landing on the client and use a RemoteEvent
to report this back to the server?
Thanks for the help!