Best way to do a debounce

Hi, I am making my input script and I was wondering what is the best way to do a debounce since my debounces are very ugly and standard.

If you have any particular different method please comment it

Thanks for reading :slight_smile:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ContextActionUility = require(ReplicatedStorage.Modules.ContextActionUtility)
local TweenService = game:GetService("TweenService")
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")

local LocalPlayer = Players.LocalPlayer
local Character = LocalPlayer.Character or LocalPlayer.CharacterAdded:Wait()

local Debounce = false

local function Inputs(actionName,inputState)
	if actionName == "Slide" and inputState == Enum.UserInputState.Begin and not Debounce then
		Debounce = true
		local FieldOfViewOut = TweenService:Create(workspace.CurrentCamera,TweenInfo.new(0.1,Enum.EasingStyle.Sine,Enum.EasingDirection.Out),{FieldOfView = 80})
		local FieldOfViewIn = TweenService:Create(workspace.CurrentCamera,TweenInfo.new(0.1,Enum.EasingStyle.Sine,Enum.EasingDirection.Out),{FieldOfView = 70})

		local HumanoidRootPart = Character:FindFirstChild("HumanoidRootPart")
		local raycastParams = RaycastParams.new()
		raycastParams.FilterDescendantsInstances = {Character}
		raycastParams.FilterType = Enum.RaycastFilterType.Exclude

		local direction = HumanoidRootPart.Position + HumanoidRootPart.CFrame.LookVector 

		print(direction)
		local bottomResult = workspace:Raycast(HumanoidRootPart.Position, Vector3.new(0,-100,0), raycastParams)
		local wallResult = workspace:Raycast(HumanoidRootPart.Position, direction, raycastParams)

		if bottomResult then -- this checks if the players bottom ray is too high up
			local Distance = math.round(bottomResult.Distance) 
			if bottomResult.Distance <= 10 then
				print("Enough distance to slide: "..Distance)
			else
				print("Not enough to slide: "..Distance)
			end
		end

		FieldOfViewOut:Play()

		local WallCheck = RunService.Stepped:Connect(function(dt)
			if wallResult then
				print(wallResult.Instance)
			end
		end)

		task.wait(2)

		WallCheck:Disconnect()
		FieldOfViewIn:Play()
		Debounce = false
	end
	
	if actionName == "Menu" and inputState == Enum.UserInputState.Begin then
		print("Menu")
	end
end

local function BindAll()
	ContextActionUility:BindAction("Menu",Inputs,true,Enum.KeyCode.M)
	ContextActionUility:SetTitle("MENU")
	ContextActionUility:BindAction("Slide",Inputs,true,Enum.KeyCode.F)
end

local function UnbindAll()
	ContextActionUility:UnbindAction("Menu")
end

BindAll()
1 Like

To do a denounce you basically do:

--Variables
local debounce = false
--do stuff
debounce = true
--do stuff
debounce = false

Yes, I know that. That’s what I do. I want to learn if there are any better variations of debounces.

I’m not sure if there actually is, another way would be to simply put a wait() or task.wait() and simply wait, other than that I’m not sure what could exist, basically a debounce waits for stuff to happen, you can do thsi with a bunch of things, Attributes, objects being activated/deactivated, transparency changing etc. there’s an immeasurable amount of debounce a

1 Like

You could do it like this.

local CooldownTime = 2 -- What ever you want
local LastUpdate = os.time() - CooldownTime

if os.time() - LastUpdate >= CooldownTime then
	LastUpdate = os.time()
	-- More code here
end
2 Likes

There is this recent thread… interesting way of debounce, works well, but slightly limiting… but its another way:

1 Like

One problem with that, the script will start by using the debounce making the code work 2 seconds after the initialization. Instead, you should set the defining variable LastUpdate to 0

local CooldownTime = 2 -- How long you need to wait to run the code again
local LastUpdate = 0 -- Defining time to 0 so there is no wait on startup

if os.time() - LastUpdate >= CooldownTime then
	LastUpdate = os.time()
	-- More code here
end
2 Likes

Although I would recommend having separate input functions for the actions, there aren’t any better alternatives to debouncing in this situation, if that’s what you’re meaning…

BUT another variation of debounce would be one that utilizes return, an inversed comparison, and de-nests the logic. I find this method is often times easier to read and prettier to look at.

This is an example of a nested debounce (what you’re currently doing):

local debounce = true -- Initializes debounce bool
event:Connect(function() -- Placeholder event
    if debounce then -- if debounce == true then
        debounce = false
        --code
        debounce = true
    end
end)

and here’s a non-nested debounce, which operates the same as the above:

local debounce = false -- Initializes debounce bool (false instead of true, as to avoid a 'not' in the debounce)
event:Connect(function()
    if debounce then -- if debounce == true then
        return -- Breaks/stops the function
    end
    debounce = true -- Setting debounce to true will cause the above 'if' comparison to catch subsequent calls
    --code
    debounce = false
end)

It’s up to personal preference which one you want to use, the non-nested version is arguably less performant but it would hardly make a difference in a trade-off for readability.