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:
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.
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:
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.
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()
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?
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).
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.
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