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.
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!
I only need my code to activate when a player who has a certain tool, who touches the object has the ability to enable and disable the SurfaceGui or frame through the player.
Edit: To try and clear any confusion, this is the type of code I currently have so far which works best. However, I think it still disables it after a few seconds automatically though:
script.Parent.Touched:Connect(function(marker)
if marker ~= nil and marker.Parent ~= nil and marker.Parent:FindFirstChild("CardNumber") ~= nil and marker.Parent.CardNumber.Value == 55 then
copy.Enabled = true
copy.ImageButton.LocalScript.Disabled = false
task.wait(5)
if marker ~= nil and marker.Parent ~= nil and marker.Parent:FindFirstChild("CardNumber") ~= nil and marker.Parent.CardNumber.Value == 55 then
copy.Enabled = false
copy.ImageButton.LocalScript.Disabled = true
task.wait(5)
else
copy.Enabled = false
copy.ImageButton.LocalScript.Disabled = true
end
My post was only meant as a reference point to solve all the issues mentioned. If you only want to show the gui if the local player is holding a specific tool, then I suggest creating the touched connections ConnectTouched() whenever the player is holding the tool. Then call ClearAllConnections when the player stops holding the tool.
As far as only allowing the the local player to change the surfacegui, we can just add a few lines of code at the top:
local players = game:GetService("Players")
local LocalPlayer = players.LocalPlayer
and add a filter inside the ConnectionFunction that first checks for the humanoid, then checks to see if it is the local player:
local function ConnectTouched()
for i, partInstance in pairs(partsThatFireTouched) do
touchedConnections[partInstance.Name] = {
TimeForResume = 0;
ConnectionFunction = function(hit)
local humanoid = hit.Parent:FindFirstChild("Humanoid")
if humanoid then
local player = players:GetPlayerFromCharacter(humanoid.Parent)
if player and player.UserId == LocalPlayer.UserId then
--It's the local player
local needsToDisconnect = PerformHit(hit, partInstance)
if needsToDisconnect then
touchedConnections[partInstance.Name].Connection:Disconnect()
touchedConnections[partInstance.Name] = nil
end
end
end
end;
}
touchedConnections[partInstance.Name].Connection = partInstance.Touched:Connect(touchedConnections[partInstance.Name].ConnectionFunction)
end
end
Ok i changed the script many times but i think this will work:
Also “perms” is meant to make the gui dissapear when you touch it for the second time(i had no good name sorry)
local perms = false -—i had no name for this, basically what it does is when you leave the part it enabled the option to disable the gui
local debounce = false
script.Parent.touched:connect(function(hit)
if hit.Parent:FindFirstChildWhichIsA(“Humanoid”) then
if not debounce then
debounce = true
if perms then
SurfaceGui.Enabled = false
else
SurfaceGui.Enabled = true
end
end
debounce = false
end
end)
script.Parent.TouchEnded:connect(function()
if SurfaceGui.Enabled == false then
perms = false
else
perms = true
end
end)
One of the problems currently, is that I am copying the SurfaceGui from Workspace and putting it into PlayerGui in the script. Since I can still reference it in the same script, I am currently detecting it in a Script and not a Localscript.
Should I try it in a separate LocalScript, or keep it in the same Script?
Edit: Also, there is a lot of stuff that says it is “unknown”.
local cooldown = os.clock()
script.Parent.Touched:Connect(function()
if os.clock() - cooldown >= 5 then cooldown = os.clock() else return end
if SurfaceGui.Enabled then
-- Do stuff
SurfaceGui.Enabled = false
else
-- Do stuff
SurfaceGui.Enable = true
end
end)
No need to use wait or anything lik tht, in fact I hate the usage of wait and try to limit its usage as much as possible.
Hmm…it still goes disabled after a couple of seconds, once I have touched the board once.
I know using an extra .Touch event might not be the best way to do this, so what could I do instead that would work better?
Even when I add the extra .Touch event, the first and second touch works. But the cycle doesn’t loop though and I have tried using a while wait(5) do loop. The problem is is that it doesn’t really work properly each time and when I touch it for the 3rd 4th time for example, the .Touch no longer works.
local cooldown = os.clock()
script.Parent.Touched:Connect(function(hitPart)
if not hitPart.Parent:FindFirstChildWhichIsA("Humanoid") then return end
if os.clock() - cooldown >= 5 then cooldown = os.clock() else return end
if SurfaceGui.Enabled then
-- Do stuff
SurfaceGui.Enabled = false
else
-- Do stuff
SurfaceGui.Enable = true
end
end)
Just realized that any object can trigger the .Touched event lol.