How to add a pre-delay on player's jump

I’m not sure what the proper term is, so I’m referring to it as “pre-delay”.

I am making a movement system where you can only jump once after leaving the ground, unlike the default Roblox movement of bunnyhopping. The problem is that I made it such that you can jump again only once you land or touch the ground. However, this system is incredibly flawed as you must land precisely press space once you land on the ground, and if you fail to do so, it makes the overall experience not smooth and might even throw you off.

I want to make it such that even if the player presses the space beforehand like.0.2 seconds earlier, it will execute the jump again once the player lands on the ground.

I’ve tried task.delay(), but it isn’t reliable as sometimes it will execute it a few milliseconds after landing, but I want it to be immediate.

The closest replication of what I’m looking for is the default Roblox’s jumping system where you would still execute the jump if you press them beforehand, without the bunnyhopping.

Please, any help will be appreciated :slight_smile:

the term you’re looking for is a “jump buffer”. you have to track when the space bar is pressed so that at the moment when the player character lands, you can check if the time difference between the 2 events is less than 0.2s.

i have no idea about the general way to implement it, so here’s a fairly hastily whipped script for you to mess with:

local JumpIntent = false
local JumpTimer = 0

game.UserInputService.InputBegan:Connect(function(Input, GPE)
	if Input.KeyCode == Enum.KeyCode.Space and Input.UserInputState == Enum.UserInputState.Begin then
		JumpIntent = true
		JumpTimer = 0.2
	end
end)

game["Run Service"].Heartbeat:Connect(function(dt)
	JumpTimer -= dt
	
	if JumpTimer <= 0 then
		JumpIntent = false
		print("buffer period expired")
	end
end)

script.Parent.Humanoid.StateChanged:Connect(function(Previous, Current)
	if Current == Enum.HumanoidStateType.Landed and JumpIntent then
		script.Parent.Humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
		print("jump was buffered (" .. JumpTimer .. "s)")
	end
end)
1 Like

The RunService event seems pretty unnecessary. You have the right idea though. You could just os.clock() to get the duration instead of having to decrement a value:

local SpacePressed

UserInputService.InputBegan:Connect(function(Input, Processed)
	if (Processed) then return end
	
	if (Input.KeyCode == Enum.KeyCode.Space and Humanoid:GetState() == Enum.HumanoidStateType.Freefall) then
		-- Pressed space while humanoid was in freefall state
		SpacePressed = os.clock() -- Store current CPU time
	end
end)

Humanoid.StateChanged:Connect(function(OldState, NewState)
	-- Humanoid's state has changed
	if (SpacePressed ~= nil and NewState == Enum.HumanoidStateType.Landed and (os.clock() - SpacePressed) <= 0.2) then
		-- Humanoid has landed
		Humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
	end
end)

Seems to work! I’ll clean it up a little though, I’ll update you.

Do I replace or add them to the previous script?

his script is much more cleaner & pretty much does the same behaviour, replace it.

sorry for replying to this thread. yes, the solution worked. but I’m wondering if there are there any alternatives than using statechanged?

You could check the humanoid’s FloorMaterial property. If they are in the air, it’ll be equivalent to Enum.Material.Air. If it is not, you know that they’re on the ground.

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