A debounce modules that work on everything

A super simple modules to handle the debounce for you
Debounce Modules.rbxm (5.3 KB)

Example:

local Debounce = require(script.Parent.Parent.Debounce)

Debounce.new(script.Parent):LinkSignal("MouseButton1Click", function()
	print("hello world, running in debounce")
	wait(2)
end)
7 Likes

Awesome, this works very nicely. It helps me out a bunch.

2 Likes

Overview

This is a simple wrapper for implementing a debounce when an instance’s event is fired. You decide how long the debounce lasts for by extending the duration of the function’s call with a wait or otherwise.

Debounce.new(Button)

Creates a new Debounce object, responsible for one instance’s event’s debounce.

Parameters

  • Button - an instance to wrap the Debounce object in. Due to its implementation, it does not have to be a TextButton or ImageButton, it just has to be of type Instance.

Returns

  • A Debounce object.

Debounce:LinkSignal(SignalName, Function)

Wraps the event binding (Function) in a debounce property setting, prohibiting any further fired events until the binding finishes yielding.

Parameters

  • SignalName - the name of the RbxScriptSignal to bind to the Debounce object’s instance.
  • Function - the function to be wrapped any time the event is fired

Returns

  • A RbxScriptConnection that denotes the binded event. Calling :Disconnect on this connection unlinks the signal.

Source Code

Debounce = {}
Debounce.__index = Debounce

function Debounce.new(Button)
	local Debounce_Ins = {}
	setmetatable(Debounce_Ins, Debounce)

	Debounce_Ins.Button = Button

	return Debounce_Ins
end

function Debounce:LinkSignal(SignalName, Function)
	local Running = false
	
	return self.Button[SignalName]:Connect(function(...)
		if not self.Running then
			self.Running = true
			
			Function(...)
			self.Running = false
		end
	end)
end


return Debounce
cleaned up and fixed
local Debounce = {}
Debounce.__index = Debounce

function Debounce.new(instance)
	local self = {
		Instance = instance,
		Running = {}
	}
	
	return setmetatable(self, Debounce)
end

function Debounce:LinkSignal(event, binding)
	local bindingId = newproxy()
	return self.Instance[event]:Connect(function(...)
		if self.Running[bindingId] then return end
		
		self.Running[bindingId] = true
		binding(...)
		self.Running[bindingId] = nil
	end), bindingId
end

return Debounce

I think even going for a single functional implementation would be cleaner, since the original introduces bugs if you naturally create a single object from Debounce.new and connect multiple events:

local function Debounce(instance, event, binding)
	local Running = false
	return instance[event]:Connect(function(...)
		if Running then return end

		Running = true
		binding(...)
		Running = false
	end)
end

return Debounce

Usage:

local Debounce = require(path.to.Debounce)

local button = script.Parent

local connection = Debounce(button, "Activated", function(input)
	print("hello world, running in debounce")
	print(input.Position)
	wait(2)
end)
8 Likes

Is the debounce yielding or non-yielding? Can we debounce inside a debounce?

1 Like

Wow, that’s so cool but like when.

1 Like

It’s non-yielding, and currently you can’t do debounce inside a debounce
(If you really want to do debounce inside a debounce, change the Function name from LinkSignal to Connect)

1 Like