Wait() for every time the Touch Functions are Called; not working properly [SOLVED]

The same debounce for both blocks of code?

2 Likes

Yeah i don’t really know but i think so.

1 Like

This code is going to produce a memory leak due to the nested event connections.

1 Like

What type of memory is susceptible for it to be leaked?

1 Like

So we are stepping on boards, from one board to the next … and you want a GUI to show only when you’re on a board? Or more of a delay on when the GUI is disabled?

1 Like

Every time you :Connect it creates a RBXScriptsignal like Instance.new() which takes memory unless it’s :Disconnected or the script is destroyed.

I believe you are looking for something like this with touch and touch ended for enabling GUI.

It should do the job and if not there is the alternative listed as Zone+ region3.

2 Likes

Firstly, the board is disabled. I want to enable it when I touch the board the first time with a tool (that works). Then it will wait for a few seconds before you can touch it again (with the same tool) and for it to become disabled.

The cycle loops when you touch it for the 3rd time.

Enable it as in walk on it? Like steps … (that turn on and off)

Just by touching it, but I don’t want to be able to keep it touched and for the frame to flicker on and off. That’s why I am using wait(), so even if you keep touching it without moving, it would only enable the frame in a given period of time.

The board is on a wall.

Would I do that two times, since I have more than one touch event or just use one in the example?

Furthermore, if I have two does it matter if I introduce two touch events together and then end the two touch_ended events together? Or do I have to end one before I can create a new one again?

I wouldn’t put a function inside a function for this. This is tricky because of touch. If you stop on the object it’s like resetting, as soon as you move it will fire again. So you need flags like a debounce.
Here is the same thing-ish … showing the same thing. Don’t matter how many times it’s touched, it will not fire again until after it has completed.

local flag = true
if touched then
if flag == true then flag = false
– code
wait(n)
flag = true
end
end

Need that just to get a handle on what is getting touched and when.
Now that you have solid testing setup. You can always set up a counter(s) or even a Boolvalue on the Explorer to test off/set for result. Even set up a toggle switch like this.

1 Like

First of all, you should not have 2 .Touched event it is completely unnecessary.

Second of all, from my understandings, you want it so when you touch a part, a gui appears.
But the second time you touch it, the gui disappears, correct?

Yes. The problem I have is when I touch it the first time and wait 5 seconds the frame disappears without me having to touch it the 2nd time. This is without the second .Touch Event but when I include that as well I seem to be getting problems.

I will, however try everybody’s script and see how they all run.

1 Like

That sounds like my script, i knew it was gonna act like that, but to solve your issue, you’re gonna need to do some stuff with .Touch and .TouchEnded.

I can’t create a script right now cuz i’m on vacation.

1 Like
  1. Use :Disconnect to disconnect the Touched event after it’s fired. [Not necessary, but can be good].
    Example:
local connection
connection = script.Parent.Touched:Connect(function(Object)
     ---code
end)

task.wait(5)
connection:Disconnect()
--You can disconnect functions within themselves too.
  1. Use task.wait instead of wait.
  2. Why are you using 2 Touched events and 2 while loops? I can smell the issues it could do.
2 Likes

I was using two because one is the first touch when it is enabled, and the second touch is when it is disabled. Then it loops again for the first one and vice versa.

It seems like I do not need the extra event, but that was what I was wondering.

Edit: @Valkyrop,I think the problem is, is when I disconnect the .Touched Event afterwards, the frame still automatically disables. However, not only that but the whole event then only runs once because I have disconnected it. Then I can’t enable it again.

Ok i’ll try to make a script of some form
Uhh something like this maybe?:
I tried making it simple

Local perms = false —i had no name for this, ——basicly what it does is when you leave the part it enabled the option to disable the gui
Local debounce = false
Part.touched:connect(function()

if not debounce then
debounce = true

Gui.enabled = true

if perms then
perms = false
Gui.enabled = false

end
end
debounce = false
end)

Part.touchEnded:connect(function()
if Gui.Enabled == false then
perms = false
else
perms = true
end)

Edit: I realized that this will only work the first time and the the gui will never open again,
Its also getting late for me, so i’ll not be able to help, have a nice day.

Edit 2: Because it works the first time, you could create some sort of ”loop” if you know what i mean. Like when the gui has appeared and then dissapeared it goes back to the orginal status.

1 Like

I think I am still getting the same issues. First time I turn it on, 5 seconds later it disables again.

Thanks for the tip!

Is ‘debounce’ the same as ‘perms’ in your example?

The code provided will create a new while loop every time anything touches the part, including the baseplate/another part/players. Also, Touched events need a debounce otherwise they can run many, many times in a short amount of time. Instead of using wait() since it’s known to be very inaccurate, it’s best to use an end point in time. As others have said, that code can also lead to memory leaks which will eventually lag your game. Don’t worry, I recycled some of my code so you can use as a reference :).

If you need a lot of touched Events that all use the same code, then I suggest doing something like this so it’s very easy to read and :Disconnect the touched events:

local touchedConnections = {}
local partsThatFireTouched = {
	--Put anything you want a touched event for in here
	game.Workspace:WaitForChild("Part1"), game.Workspace:WaitForChild("Part2"), game.Workspace:WaitForChild("Part3")
}

local function PerformHit(hit, partInstance)
	if DateTime.now().UnixTimestampMillis >= touchedConnections[partInstance.Name].TimeForResume then
		--Touched Event is allowed to fire again
		--You can filter this if you need different actions for different parts
		
		--Reset the timer for 5 seconds from now:
		touchedConnections[partInstance.Name].TimeForResume = DateTime.now().UnixTimestampMillis + 5000 --> 5000 milliseconds(5 seconds)
		if partInstance.SurfaceGui.Enabled then
			partInstance.SurfaceGui.Enabled = false
		else
			partInstance.SurfaceGui.Enabled = true
		end
		--return true if you need to disconnect this touched event
	end
end


local function ConnectTouched()
	for i, partInstance in pairs(partsThatFireTouched) do
		--Create a function for the part being touched and store it within its own key within the touchedConnections table
		touchedConnections[partInstance.Name] = {
			TimeForResume = 0; --> handles the very first call
			ConnectionFunction = function(hit)
				if hit.Parent:FindFirstChild("Humanoid") then
					--Only runs if whatever hit it has a humanoid. Be aware this will run for NPCs with humanoids and EVERY player
					local needsToDisconnect = PerformHit(hit, partInstance)
					if needsToDisconnect then
						--If you only ever need for this connection to fire once, then you should include: return true in the PerformHit area
						touchedConnections[partInstance.Name].Connection:Disconnect() --Disconnect RBX event signal
						touchedConnections[partInstance.Name] = nil --Clear memory since we don't need this anywmore
					end
				end
			end;
		}
		--This stores the connection within that part's key and name it connection so we can :Disconnect() it later
		touchedConnections[partInstance.Name].Connection = partInstance.Touched:Connect(touchedConnections[partInstance.Name].ConnectionFunction)
	end
end

local function ClearAllConnections()
	--If you ever need to clear ALL connections (like a game reset or something)
	for partName, connectionTable in pairs(touchedConnections) do
		connectionTable.Connection:Disconnect()
		touchedConnections[partName] = nil
	end
end

ConnectTouched()

I tried to add comments in the code that explains what it does, but basically this code never yields like wait() does. Instead of waiting 5 seconds, this code checks a debounce every time a player actively collides with the part. The debounce is nothing more than setting a very accurate timer for 5 seconds into the future. The added benefit is each one of these connections operate independently from one another since their TimeForResume values are specific to that part. Hope this helped ya out!

[EDIT] Grammar/Deleted a lot of whitespace

3 Likes