Best way to debounce?

Here is the debounce function (I know it’s not perfect), however I didn’t mean to say that touched is failing to fire (its that it is firing too many times between the wait’s).

		drop.Touched:Connect(function(hit) -- This may need tweaking if it fires too much and could possibly cause lag
			if hit.Name == "Detector" or hit.Name == "Collider" then -- dont use or
				print("Drop hit detector or collider")
				task.wait(0.1) -- Ignore this it was for testing
				drop:SetAttribute("Debounce", true)
				task.wait(0.2)
				drop:SetAttribute("Debounce", false)
			end
		end)

		Debris:AddItem(drop, 20)

Why are you waiting 0.1s before setting the debounce? Maybe that’s the issue?
Also what’s the part of the code where you actually double the cash?

When “drop” is touched by the Detector or the Collider, after 0.1s turns Debounce attribute to True, after 0.3s turns attribute to false; if the “drop” still touching a Detector or Collider will trigger the function again, caused by mutiple touches.

You could use TouchEnded:Connect() event too, to know where to disable the Debouce attribute.

When hit Detector or Collider, Debounce attribute to true. And when drop.TouchEnded() Debounce attribute to false.

Or consider another approach as ThanksRoBama, as if you are already using OOP, handling the “boost” of the drop in a different way, considering different events to do it

Why do you need to set the debounce to false at all, if you’re just going to destroy the dropper after 20 seconds?

Im not sure why you asking to me :sweat_smile:
Thats the OP’s conveyour belt and drops, idk whats OP’s plan with the drops the debounces etc
I just mentioned that the issue is related with multiple touches that the drop has against the collider and detector thing

1 Like

Hi, that 0.1 was just for testing purposes, sorry I left it in the post. However, I have tried the code without it and the drops can still fire the touched event more than once.

Sorry, the 0.1 was just for testing purposes however the issue still continues after I remove it. I have heard about the TouchEnded event before, but I was told it was unreliable.

i think its because you forgot to check if the debounce attribute was true or not and to make it not run if its true

should be something like

if drop:GetAttribute("Debounce") == false and (hit.Name == "Detector" or hit.Name == "Collider") then

1 Like

If you did set your debounce attribute to true when using Touched event, then whats the difference on not using TouchEnded event?, Im not saying its perfect, Im saying the issue its related with multiple touches from the drop.

1 Like

Whenever the object gets into the upgrader, you could immediately add it to a table and make sure when objects go thru it they arent in the table before adding value to the object.

1 Like

Unfortunately this still does not work completely, although it appears to decrease the amount of drops being multiplied more than once. For now I’ll try to configure a table based system (possibly a module in itself) using region3 or something similar. When I complete I will post it here for anyone to use.

1 Like

if u just want to upgrade the drop once, u can just set the debounce once only

local db = false
item.Touched:Connect(function(hit)
	if hit.Name == "Upgrader" and db == false then
		db = true
		--do stuff
	end
end)
1 Like

Thanks for the idea, but TouchEnded is also buggy. As when there is a high volume of drops it seems like the event fires at random increments and cannot cope with lag.

This would work in my game demonstration however in practice the drop will go through multiple upgraders and then a collector before it is deposited (which all obviously need to debounced as well).

I’ve never been a fan of TouchEnded, preferring instead to use spatial query, but in this case I reckon using two parts with .Touched connected¹ might work? One as an entrance which adds the debounce and one as an exit which clears the debounce. (A backup timer would be good)

If you’re designing a sandbox tycoon game similar to that of Miner’s Haven, checking to see if the part enters another tile’s space could also serve to clear the debounce.

¹: Using your method of .Touched on the money blocks themselves would also work, just another condition to check.

1 Like

U can have a counter variable and increase it by 1 each upgrader touched
Here is some code considering u have the upgraders in an arrangement of e.g “Upgrader1”,“Upgrader2” and so on

local DropItem = script.Parent

local MainString = "Upgrader"
local counter = 1

DropItem.Touched:Connect(function(hit)
	if hit.Name == MainString..counter then
		counter +=1
		print("Touched")
	end
end)

this script can give debounce for each part i guess
(put this script in detector)

local hits = {}
local detector = script.Parent
detector.Touched:Connect(function(hit)
if hit.Parent.Name == “dropped item” and not hits[hit.Parent] then
hits[hit.Parent] = true
—your script here
end
end)

im sorry if its not what you want

Hi Everyone, Sorry I have been extremely busy (just replying now so the topic does not auto close). However I have almost completed the script and would love to hear some critiques once I post it!

Hi again, I have finally created the debounce. This model I have linked below will work for normal scripts whilst I still have to make edits to finish the OOP version/module script.


Demo of the debounce - Red, purple, and blue bricks are Part1, 2, and 3 respectively.

Applications

This debounce will work in situations where there is multiple parts passing through many touch detectors/upgraders. It also works fine with single parts and single detectors.

Setup

To setup the debounce for your own follow these steps:

  1. Substitute my variables for your own.
    a) Decide on how many touch detectors you need (I have 4 in my demonstration) but you can delete or add however you see fit.
    b) Change the touch detector variables’ name to that of your upgraders.
    c) Specify the touch detectors directory (optional: use waitforchild())
    d) Decide on how many parts you want to be detected and substitute their names into the code.

  2. Specify db_Time or the debounce cooldown time in seconds. The time between deboucing always stays the same so make sure one debounce interval works for all detectors.

  3. On the part(s) you want detect create 1 or 2 attributes depending on your use:
    a) A “Debounce” boolean set to false.
    b) FOR TYCOONS: A “Worth” number containing the original value of the drop (if you are changing something different instead of worth simply change this second attribute to whatever it is you desire to be debounced).

  4. Enter the directory of the parts you want to be detected inside the filterObjects table.

  5. If you want to view the debounce in action, uncomment the print statements.

Code

local TouchDetector = workspace:FindFirstChild("Test").Detectors.TouchDetector
local TouchDetector2 = workspace:FindFirstChild("Test").Detectors.TouchDetector2
local TouchDetector3 = workspace:FindFirstChild("Test").Detectors.TouchDetector3
local TouchDetector4 = workspace:FindFirstChild("Test").Detectors.TouchDetector4


local db_Time = 0.5

local filterObjects = {workspace.Test.Part2, workspace.Test.Part1, workspace.Test.Part3}

local params = OverlapParams.new()
params.FilterType = Enum.RaycastFilterType.Whitelist -- WHITELIST MAKES OVERLAP PARAMS IGNORE ALL OBJECTS EXCEPT THOSE IN THE FILTER OBJECTS (BLACKLIST DOES THE OPPOSITE)
params.FilterDescendantsInstances = filterObjects


local TouchDetectors = {}


while TouchDetectors do task.wait()
	local TouchDetectors = {
		touchingList = workspace:GetPartsInPart(TouchDetector, params),
		touchingList2 = workspace:GetPartsInPart(TouchDetector2, params),
		touchingList3 = workspace:GetPartsInPart(TouchDetector3, params),
		touchingList4 = workspace:GetPartsInPart(TouchDetector4, params)
	}

	for i,v in pairs(TouchDetectors) do
		for i,v in pairs(v) do
			local debounce = v:GetAttribute("Debounce")
			if not debounce then
				--print(i, v)
				local worth = v:GetAttribute("Worth")
				v:SetAttribute("Worth", worth * 2)
				--print(v:GetAttribute("Worth"))
				v:SetAttribute("Debounce", true)

			else
				--print("Debounce off fired")
				task.wait(db_Time)
				v:SetAttribute("Debounce", false)

			end
			
		end
	end
end

View the full demonstration at:

I hope this helps everyone as there is suprisingly little knowledge in such an important aspect of development. Also please credit me if you use this, thanks :smile:

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.