Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
COMMUNITY QUESTION

How can I add a debounce to this?

I tried to even tried to add waits. It's a sliding door and it has sound to it, but the door glitches too much and plays the sound again and again because it keeps detecting humanoid. How can I create a debounce?


bin = script.Parent

openTime = .5
closeTime = 0

openState = bin.DoorScript.open

function touch(hit)
	if hit.Parent == nil then return end
	local p = game.Players:playerFromCharacter(hit.Parent)
	if p ~= nil then
		if openState.Value then
			closeTime = openTime -- Prolong open time
		else
			openState.Value = true
			closeTime = openTime
			while closeTime > 0 do
				wait(0.1)
				closeTime = closeTime - 0.1
			end
			openState.Value = false
			wait(2)
		end
	end
end

bin.trigger1.Touched:connect(touch)

2 answers

The idea behind a "debounce" is that only one event can touch anything at the same time.

You can actually think of it in a way as "disabling" the event:

local enabled = true
-- begin in a state where ALL events matter

function event()
	if enabled then
		-- I'm enabled!
		enabled = false -- I'm not longer "enabled" (to everyone else)
		-- ...but I'm gonna do my thing, and then re-enable me
		for i = 1, 10 do
			wait()
			-- do whatever
		end
		enabled = true -- I'm done, so everyone else can start up
	end	
end

Three parts:

  • Define some sort of enabled or disabled variable (it's often called debounce but that name is so completely undescriptive you shouldn't use it)
  • At the beginning of an event, check that you're allowed to continue -- if enabled or not disabled. If it's a go:
  • Disable yourself (enabled = false or disabled = true)
  • Do whatever you would do if you weren't adding a debounce
  • Enable yourself (enabled = true or disabled = false)

I am not particularly fond of the debounce pattern. Since you're effectively disabling the thing, while anything is moving, all input is ignored. That's not usually intuitive or fun to deal with as a player.

Instead, I like to make my events instantaneous, and a loop in the background responds to variables set.

For instance, consider this simple sliding door with an open and a close (including a debounce)

local door = script.Parent
local home = door.CFrame

local enabled = true

function open()
	if enabled then
		enabled = false
		for i = 1, 20 do
			door.CFrame = home + Vector3.new(0, i, 0)
			wait()
		end
		enabled = true
	end
end

function close()
	if enabled then
		enabled = false
		for i = 1, 20 do
			door.CFrame = home + Vector3.new(0, 20 - i, 0)
			wait()
		end
		enabled = true
	end
end

I prefer this shape:

local door = script.Parent
local home = door.CFrame
local speed = 0

function open()
	speed = 0.5
end

function close()
	speed = -0.5
end

local y = 0
while wait() do
	door.CFrame = home + Vector3.new(0, y, 0)
	y = y + speed
	if y > 20 then
		y = 20
	end
	if y < 0 then
		y = 0
	end
end

Rather than actually doing the work for opening & closing, you just say the direction to go and another loop takes care of it. This simplifies the events and reduces how much you repeated, while making the looping part only slightly more complicated.

Why? The debounce pattern is an attempt to avoid illegal states -- you use debounce to prevent opening and closing at the same time, or opening & opening at the same, etc.

With this design, the only state is whether or not you are currently opening or closing -- there's no way to mess up and let it both open and close because for any number you set speed to, you get a well-behaved result.

Try this:

bin = script.Parent

openTime = .5
closeTime = 0

Debounce=false

openState = bin.DoorScript.open

function touch(hit)
if Debounce==false then
    Debounce=true
    if hit.Parent == nil then return end
    local p = game.Players:playerFromCharacter(hit.Parent)
    if p ~= nil then
        if openState.Value then
            closeTime = openTime -- Prolong open time
        else
            openState.Value = true
            closeTime = openTime
            while closeTime > 0 do
                wait(0.1)
                closeTime = closeTime - 0.1
            end
            openState.Value = false
            wait(2)
        end
    end
Debounce=false
end
end

bin.trigger1.Touched:connect(touch)

(Sorry about no identations, i'm on my phone).


Anyways, I just added a value that when set to false will allow the function to be triggered, and when it's true it won't allow it to go through. I believe it should work now. If yoy have any further questions/problems, please leave a comment below. Hope I helped :P

This discussion is preserved as it was. New answers, comments, and votes are closed.