How to detect when player lands on the ground

while true do
	
	local MyParams = RaycastParams.new()
	MyParams.FilterDescendantsInstances = {char}
	MyParams.FilterType = Enum.RaycastFilterType.Blacklist
	
	local result = workspace:Raycast(torso.Position, char.MyPart.CFrame.UpVector * 2.9, MyParams)
	
	if result and result.Instance and part.Landing.Playing == false then
		part.Landing:Play()
	end
	
	task.wait()
	
end

Here is my current code for detecting when the player lands. This functions by using a part which I inserted and welded to the player (named MyPart) to shoot a raycast beneath the player. When the player lands from a high enough height, their feet will slightly clip through the ground upon landing, which lets the raycast reach below the player for a split second. I’m 100% sure this is not the most efficient way to detect this issue, I’ve looked on YouTube and couldn’t find any videos and I couldn’t find anything on the devforum which worked for me

The current issue with my system is that it’s delayed (doesn’t play the sound for landing until about a quarter of a second after the player lands) and it’s not an efficient way to detect a player landing

1 Like

Another thing, “MyPart” is upside down and i’m using UpVector since as far as I know, there’s no DownVector and i’m not sure how to redirect the ray downwards

Humanoids have a Landed state that you can detect with Humanoid.StateChanged

Humanoid.StateChanged documentation

Humanoid.StateChanged:Connect(function(OldState : Enum.HumanoidStateType, NewState: Enum.HumanoidStateType)
	if NewState == Enum.HumanoidStateType.Landed then
		print("Humanoid landed")
	end
end)
1 Like

I came across this while looking on the devforum, but the issue is that it only seems to work about every other time

.StateChanged hasn’t been inconsistent for me, but another workaround I can think of is checking the Humanoid.FloorMaterial ~= Enum.Material.Air to see if the client is in the air or on the ground

3 Likes

Ok, I think I found the issue while experimenting with this. When I check in a local script, it seems to not be delayed anymore. For whatever reason, a server script is delaying the response time, so I’ll have to use a remote event to player the audio for everyone. Is this the most efficient way to write this?

while true do

	if hum.FloorMaterial == Enum.Material.Air then
		Toggle = true
	elseif Toggle == true then
		Toggle = false
		print("landed")
	end

	task.wait()
end

Personally I’d bind the loop to RunService.Heartbeat and have the sounds be client-authoritative to avoid using remotes and unnecessary network overhead