How to ACTUALLY accurately detect when a player jumps

Your first method might actually just work fine, but I think you also need to do a raycast to see if the player is touching any ground.

1 Like

most of the time when the character lands or jumps .StateChanged doesnt trigger

raycast wouldn’t work because pointing it from the center of the character’s foot would mean that if the character is standing on the edge of it’s foot the raycast will detect as not standing, when actually the character is standing on a part, just on the edge of its foot

Well, if something works with a standard rig and doesn’t work with your rig, there may be something wrong with your rig. Maybe you’re troubleshooting the wrong problem here.

I never made my own rig so I’m not sure what it could be though.

I guess a smarter way to do it is incorporate JumpRequest event while using humanoid.Jumping to see if it’s currently jumping before being able to operate.

Are you running this script on the Server or the Client?

The client is usually better at detecting humanoid events.

1 Like

You cast it down from the middle of the character’s HumanoidRootPart because that part always needs to stay on ground or the character will fall off the edge.

Never raycast from body parts unless you have a very good reason to.
Also, I suggest you do the raycast like 0.1 seconds after the jump, otherwise it might still hit the ground and think the player is standing.

Alternatively, you can also just raycast to the ground anyways and just check if the distance is more than 3.5 studs to count as a jump.

The issue he is talking about is referring to when a player is barely standing on a ledge like so:

Because the character is centered over nothing, the raycast won’t work properly.

The best way to solve this problem is to detect the jump/landing on the client, then fire a RemoteEvent to the Server. It would be something like this:

Client (StarterCharacterScripts):

local event = (the remote event)
local char = game.Players.LocalPlayer.Character

local countJump = false

char.Humanoid.StateChanged:Connect(function(old, new)
    if new == Enum.HumanoidStateType.Jumping then
        countJump = true
    elseif new == Enum.HumanoidStateType.Landed then
        if countJump then
            countJump = false
            event:FireServer()
        end
    end
end)

Server (ServerScriptService):

local event = (the remote event)
local debounces = {}

local jumpCD = 0.5 -- minimum time between jumps

event.OnClientEvent:Connect(function(plr))
    if not table.find(debounces, plr.Name) then
        table.insert(debounces, plr.Name)
        -- update leaderstats or whatever
        task.wait(jumpCD)
        table.remove(debounces, table.find(debounces, plr.Name))
    end
end)

The only flaw to this is that an exploiter could fire the remote event. However, a cooldown on the server prevents it from going up too quickly.

More raycasts should solve this, or doing a shapecast down which is just a singular block raycast that should hit about anything.