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.
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)
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)
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.