I’ve been trying to write a function to prevent bunny-hopping (jumping constantly), and my current version works fairly well. If you only press space when you want to jump, this function works fine. But if you hold down the spacebar, you will always manage to get in two consecutive jumps before the script stops you. Any suggestions?
My current code:
(Notes: hum = the character’s humanoid, UIS = UserInputService, without the wait() line, you can’t jump at all)
local function jump()
if hum:GetStateEnabled(Enum.HumanoidStateType.Jumping) then
wait()
hum:SetStateEnabled(Enum.HumanoidStateType.Jumping, false)
delay(2, (function()
hum:SetStateEnabled(Enum.HumanoidStateType.Jumping, true)
end))
end
end
UIS.JumpRequest:Connect(jump)
Not really scripting based, but placing a notice on the screen for when they exceed the jump timer would at least tell them what their doing wrong and they wouldn’t believe it to be flawed.
local UserInputService = game:GetService("UserInputService")
local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
local Player = Players.LocalPlayer
local Character
local Humanoid
local Landed = 0
local JumpState = true
local Jumping = false
local function SetJumpState(state)
-- Avoid calling Humanoid:SetStateEnabled more than once
if JumpState ~= state then
JumpState = state
Humanoid:SetStateEnabled(Enum.HumanoidStateType.Jumping, state)
end
end
local function OnCharacter(character)
Character = character
Humanoid = character:FindFirstChildOfClass("Humanoid")
Humanoid:GetPropertyChangedSignal("FloorMaterial"):Connect(function()
if Humanoid.FloorMaterial ~= Enum.Material.Air and Jumping and JumpState then
Landed = tick()
Jumping = false
SetJumpState(false)
end
end)
end
if Player.Character then
OnCharacter(Player.Character)
end
Player.CharacterAdded:Connect(function(character)
Landed = 0
JumpState = true
Jumping = false
OnCharacter(character)
end)
RunService.Heartbeat:Connect(function()
if not JumpState and tick() - Landed > 0.5 then
SetJumpState(true)
end
end)
UserInputService.JumpRequest:Connect(function()
if Humanoid.FloorMaterial ~= Enum.Material.Air then
Jumping = true
end
end)
It waits until the player lands (from a jump) by checking FloorMaterial then starts a timer (currently set to 0.5 seconds) which is ran on a Heartbeat loop, to avoid creating multiple overlapping threads. Most of the mess is from the character reset logic.
Not letting players jump for every moment they are grounded can make for a really clunky user experience unless you show on-screen when players can start jumping again. (i.e. “I’m pressing space and it’s not working, why???”)
A more user-friendly idea (to me) would be that players who are mid-air take more damage, or to add some kind of landing animation that soaks up that time that a player is not able to jump and briefly prevents them from moving, so they know what’s up.
Another way is to have a stamina bar from which jumping could take a chunk out of - the bar would then recharge gradually. Stops people from bunny-hopping but still allows people to jump when they want to and it allows people to see why they are grounded (because no stamina left).
This anti-bunny-hopping script is for an FPS, where not being able to jump constantly is expected. If any of you have played Phantom Forces, they prevent bunny-hopping without using a stamina bar or any sort of “you can’t jump right now” notification and it works well. I’ll of course be fine tuning the wait time between jumps to make it as un-annoying as possible. If I really need to add some notification for this to make it more natural, I’ll certainly do that later. Right now I’m just looking for a solution that works.
That is a bit more complicated than I was hoping for. Luckily I won’t have to deal with the character reset logic so much, as the localscript is in the character, so it’ll naturally reset with a respawn. I’ll give something like that a shot.