Preventing Bunny-Hopping

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)
2 Likes

You can easily do

JumpEvent:Connect(function()
   Humanoid.Jump = 0
   wait(Time)
   Humanoid.Jump = 50
end)
7 Likes

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.

1 Like

Here’s a quick and messy solution I came up with:

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.

12 Likes

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.

12 Likes

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

2 Likes

I like the way Fortnite handles it. They don’t completely turn off jumping, but they slowly bring down JumpPower (or whatever UE’s equivalent is)

3 Likes

@InfinitumFrost, @buildthomas, @Billy_Dodo, @Kiansjet

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.

4 Likes

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.

1 Like

Yeah, hope it all works out!

I was thinking that jump fatigue was a good alternative to jump delay.