Problems when opening a UI with a touched part

I have a script that opens a ui when a part is touched, and then I have another localscript in the UI which lets you close it by clicking a button in the ui.

The problem is that after opening and closing the UI once, when I try to open it again it doesnt work.

https://gyazo.com/f1a0a8790c73559942adbe0e4477c705

LocalScript:

local ui = script.Parent.Parent.Parent
local button = script.Parent

button.MouseButton1Click:Connect(function()
	local things = ui:GetDescendants()
	for i, v in pairs(things) do
		if v.ClassName == "Frame" or v.ClassName == "TextLabel" or v.ClassName == "ViewortFrame" or v.ClassName == "TextButton" or v.ClassName == "ImageButton" then
			v.Visible = false
		end
	end
end)

ServerScript:

local part = script.Parent

part.Touched:Connect(function(r)
	local plr = game.Players:GetPlayerFromCharacter(r.Parent)
	local ui = plr.PlayerGui.BoatSpawn
	local things = ui:GetDescendants()
	for i, v in pairs(things) do
		if v.ClassName == "Frame" or v.ClassName == "TextLabel" or v.ClassName == "ViewortFrame" or v.ClassName == "TextButton" or v.ClassName == "ImageButton" then
			v.Visible = true
		end
	end
end)

Error:
image

The error you’re getting is because you won’t always find a character with r.Parent. You should add a check to make sure that plr isn’t nil,

part.Touched:Connect(function(r)
     local plr = local plr = game.Players:GetPlayerFromCharacter(r.Parent)
     if plr then
          -- do stuff
     end
end)

Also, you shouldn’t be manipulating anything in PlayerGui from the server, especially when its also being manipulated on the client. In your case, when you make the gui visible on the server, the player will see the change. The client then closes the gui and the player sees this but the server doesn’t recognize the change. The next time you try to open the gui on the server, the server will think that it is already open and won’t cause a change.

You should be using remote events so the server will tell the client to open the ui, and then the ui will handle it.

1 Like

The server and client have no way of communicating with each other. As @MayorGnarwhal said, use remote events.

1 Like

Script in the part that is touched:

local part = script.Parent
local event = script.Parent.Parent.RemoteEvent

part.Touched:Connect(function(r)
	local plr = game.Players:GetPlayerFromCharacter(r.Parent)
	if plr then
		local ui = plr.PlayerGui.BoatSpawn
		local on = true
		event:FireClient()
	end
end)

LocalScript in the UI

local event = workspace.AmericanBase.AmericanSpawners.BigBoatSpawner.RemoteEvent
local ui = script.Parent.Parent

event.OnClientEvent:Connect(function()
	for i, v in pairs(ui:GetDescendants()) do
		if v.ClassName == "Frame" or v.ClassName == "TextLabel" or v.ClassName == "ViewortFrame" or v.ClassName == "TextButton" or v.ClassName == "ImageButton" then
			v.Visible = false
		end
	end
end)

For some reson it doenst work and I get these errors:

In the part script:
image

In the localscript:
image

You need to tell the server who to fire the client to. So do :FireClient(plr). Also, with the Unicode character, you can refer to this page

That first error is a relatively new problem being caused in the Roblox script editor. For some reason when you press shift + enter, a weird character is added in place of a new line which will error the compiler.

Look for a line without a number next to it.
image

The second error is because you didnt’ specify which client to send the remote to

You need to put the player argument inside of that. event:FireClient(plr)

1 Like

So now everything works well, I tried adding a debounce because the player lags when staying inside the part. But the debounce doesn’t work for some reason:

local part = script.Parent
local event = script.Parent.Parent.RemoteEvent
local debounce = false

part.Touched:Connect(function(r)
	local plr = game.Players:GetPlayerFromCharacter(r.Parent)
	if plr then
		local ui = plr.PlayerGui.BoatSpawn
		local on = true
		if debounce == false then
			event:FireClient(plr)
		end
		debounce = true
		wait(1)
		debounce = false
		print("Fired")
	end
end)

Change the debounce variable to true.