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

When I use the original script (which disables the SurfaceGui after a few seconds), I don’t get any errors from any other scripts. When I try your script however, I always get this error from a different LocalScript:

Error, from a LocalScript

Maybe too many if statments, but not sure.

Could you show me line 3 of that script?

This is the 3rd line down in the LocalScript, where the error is coming from:

derp.SurfaceGui.Frame.CurrentColor.Changed:Connect(function(val)

What is derp (char limit char).

1 Like

@Mystxry12, derp is a variable like this:

derp = (script.Parent.Parent.Parent.Parent.BoardLoc.Value)

I need to get the Adornee or some sort of link for that, because the SurfaceGui is coming from the PlayerGui inside the player. It needs to get back to the Model in Workspace because it creates ImageLabels in the whiteboard. Only certain people with the tool who touch the whiteboard can edit on it. Edit:

Don’t know why the error is coming from here though, because it works before. It is only when I touch the board with the tool, that I seem to get the error when using the script for some reason.

I have no idea wts causing the issue, it doesn’t seem to come from my script.

1 Like

Wait, I think it might be because you got rid of the other if statement, which makes the SurfaceGui visible.

@Mystxry12, do I repeat the first process on the second if statement which makes it turn from enabled to disabled?

Anybody else have any ideas, as to what might be causing the issue? Or are there any better methods that might work better on this problem?

Yeah you’ll definitely want this in a local script since:

The client should probably create/clone the SurfaceGUI as it is only viewable for the client. This will automatically be taken care of for us if we replace this bit of code at the top of that previous post I made:
RobloxStudioBeta_vSQNvudw6c

local touchedConnections = {}
local players = game:GetService("Players")
local LocalPlayer = players.LocalPlayer
local partsThatFireTouched = {
	--Put anything you want a touched event for in here
	game.Workspace:WaitForChild("Part1"), game.Workspace:WaitForChild("Part2"), game.Workspace:WaitForChild("Part3")
}
--Give a SurfaceGUI for each of the parts in partsThatFireTouched:
local surfaceGUI = LocalPlayer:WaitForChild("PlayerGui"):WaitForChild("SurfaceGui")
for i, partInstance in pairs(partsThatFireTouched) do
	local clonedOfSurfaceGUI = surfaceGUI:Clone()
	clonedOfSurfaceGUI.Parent = partInstance
end

Most of the time GUIs are handled by the client in a local script. The server doesn’t need to keep track of who is seeing which SurfaceGUI; this can and should be handled by the client. It’s especially true in your case since you want the SurfaceGUI only to appear if the local player touches the part.

As far as if the code provided works, it definitely does:

It addresses every problem mentioned:

  • Uses no loops
  • Debounces based off of time (this can also be used to sync an accurate timer between client and server)
  • Does not yield the thread (it never pauses the code with wait/task.wait)
  • Memory leaks (handles clearing out the connections/data from memory)
  • Different Touched events needing different cooldowns
  • Different parts firing the Touched event
  • Debouncing everything but the local player
  • Create the SurfaceGUI on the client (further up in this post)

The only thing it doesn’t handle is when the Touched connections are made/disconnected. That’s completely up to you of where to place ConnectTouched() or ClearAllConnections in your code.

Source:
If you wish to use the Plugin …
Tag-Editor Forum, Tag-Editor Plugin

You can also do in manually … ( plugin not needed but is nice )
Run this next line in the studio’s Command line, aimed at your board to add a tag Board to it.
game:GetService(“CollectionService”):AddTag(game.Workspace.Part, “Board”)

-- Nonlocal Script 
-- in ServerScriptService
wait()

local ftf, tag = true, "Board"
local CollectionService = game:GetService("CollectionService")

local function onPartTouched(otherPart)
	if not otherPart.Parent then return end
	local human = otherPart.Parent:FindFirstChildOfClass("Humanoid")
	if human ~= nil and ftf == true then ftf = false 
		local Player = game:GetService("Players"):FindFirstChild(human.DisplayName)
		local PlayerGui = Player:WaitForChild("PlayerGui")
		-------------
		PlayerGui.ScreenGui.Enabled = true 	task.wait(5)
		PlayerGui.ScreenGui.Enabled = false	task.wait(1)
		-------------
		ftf = true
	end
end

local connections = {}
local function onInstanceAdded(object)
	if object:IsA("BasePart") then
		connections[object] = object.Touched:Connect(onPartTouched)
	end
end

local function onInstanceRemoved(object)
	if connections[object] then	connections[object]:disconnect()
		connections[object] = nil
	end
end

CollectionService:GetInstanceAddedSignal(tag):Connect(onInstanceAdded)
for _, object in pairs(CollectionService:GetTagged(tag)) do
	onInstanceAdded(object)
end

Note: Every object with the tag Board will trigger the GUI when touched by this single script.
More on CollectionService with AddTag() ,RemoveTag(), GetTagged() and HasTag()

1 Like

I think I already have the copy of the SurfaceGui, inside the PlayerGui managed and it clones it fine. However, if there is any difference in performance for if I change it to a LocalScript?

@2112Jay

  1. How do I get it work and is that manual, without the plugin? Since I don’t think the script recognises if I have the correct tool.

  2. Would I change the variables, in accordance to where the ‘Draw’ SurfaceGui is located inside the player, etc?

I might have a look at the plugin further.

The plugin keeps track of tags. It can show you what is tagged … exc. it’s a tool.
Other than that CollectionService handles tags for the studio and for the tool also.
That scripts is all you need … and to set the Board tag(s).

1 Like

@2112Jay

  1. Do I need to set the tag? I think I already have it done in the scripts, when it duplicates the SurfaceGui inside the PlayerGui. Unless that is a better way for next time.
  • I just need to figure out a way whereby I can touch it once to enable it, and then touch it again to disable it when I want to, when I have the correct tool.

What do you mean … what do you mean.
Do I need to set the tag? or How do I get it work and is that manual, without the plugin?
Both of them have total been explained in my former posts. This is so easy it’s (insert verb).
Copy/Paste that script to ServerScriptService and set a tag to Boards. You may have to actually read what has been posted.

It seems you’re bound and determined to use that double function even though everyone has told you that isn’t a greatest implication. So I leave you to it …

  • Not currently having problems, with the duplicating of the tag and it already works. Despite this, the Script currently runs in Workspace and I tried it in the game but I couldn’t get it to work.

Nevertheless, the problems come, when I am trying to make a cooldown in the middle, of when I touch the part. This is so, the SurfaceGui can’t keep flickering on and off so quickly. Yet, when I only use one .Touch event it fires, however the other if statement, which turns it back off again, doesn’t need, for the board to be touched again by anyone. Thus, it seems to go off automatically without me using the trigger, (.Touch event) and I am not sure what else to use, unless there is a better way.

When I use two touch events, I seem to be able to have to touch it to get it disabled again, after enabling it. I am torn between using it because it works, and not using it because it isn’t very effective. However, if there is a better way of doing this, without using more than one .Touch event that will work, please suggest.

“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.”

1 Like

That’s why I want to try and add a wait, but so far it hasn’t really been that effective.

I used @schaap5347’s script, and adapted it below!

Thanks to @schaap5347, who helped me solve this problem:

local perms = false 
		local debounce = false
		
		Whiteboard.Touched:Connect(function(marker)
			if marker ~= nil and marker.Parent ~= nil and marker.Parent:FindFirstChild("CardNumber") ~= nil and marker.Parent.CardNumber.Value == 324 then
				if not debounce then
					task.wait()
					debounce = true
					if perms then
						copy.Enabled = false
						copy.ImageButton.LocalScript.Disabled = true
					else
						copy.Enabled = true
						copy.ImageButton.LocalScript.Disabled = false
					end
				end
				debounce = false
			end
		end)

		Whiteboard.TouchEnded:Connect(function()
			if copy.Enabled == false then
				task.wait(1) --added wait here
				perms = false
			else
				task.wait(1) --added wait here
				perms = true

Thanks to:

@schaap5347
@Mystxry12
@2112Jay
@2Gethere_Games
@Forummer
@7z99
@Valkyrop
@dthecoolest

1 Like

No way! I’m glad i could help fix the problem.

1 Like