Hello developers. I was wanting to create a simple exit screen function for a ScreenGui in my game. So far, you press a proximity prompt to make the screen pop up and parent to the PlayerGui, where a local script can then run and set up a .Activated event for the button you click to destroy the ScreenGui. The problem is, this works the first time around, but when you click the proximity prompt and try to exit out of the screen again, it doesn’t. I’m not sure if the problem lies in the local script, the server script, or both. I’ll also include a snapshot of the explorer panel. It seems like such a simple problem, but because of how it works so inconsistently, this is what’s throwing me off.
local ProximityPromptService = game:GetService("ProximityPromptService")
local CollectionService = game:GetService("CollectionService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local StartGameFolder = ReplicatedStorage:WaitForChild("StartGameFolder")
local StartGameGui = StartGameFolder.StartGameGui
local StartGameEvent = StartGameFolder.StartGameEvent
local Modes = {
Classic = {"Diagonal"}
}
for _, prompt in CollectionService:GetTagged("startgame") do
prompt.ObjectText = "Start game"
end
local function startGame(prompt, player)
if CollectionService:HasTag(prompt, "startgame") then
local StartGuiClone = StartGameGui:Clone()
StartGuiClone.Parent = player.PlayerGui
StartGuiClone:FindFirstChild("StartGui", true).Enabled = true
StartGameEvent:FireClient(player, StartGuiClone)
end
end
ProximityPromptService.PromptTriggered:Connect(startGame)
Local script:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local StartGameFolder = ReplicatedStorage.StartGameFolder
local StartGameEvent = StartGameFolder.StartGameEvent
local connection = nil
local function startGui(startGuiClone)
connection = startGuiClone:FindFirstChild("ExitScreen", true).Activated:Connect(function()
connection:Disconnect()
startGuiClone:Destroy()
end)
end
StartGameEvent.OnClientEvent:Connect(startGui)
Hello! I believe it might be because you are cloning the GUI to the player server-side and then deleting it only client-side which may cause issues. Also make sure to check the output for any errors, those are very helpful when debugging.
Here is what I added, and it does delete the Gui, but also my character and player. I didn’t even remotely add anything having to do with either, do you know what could’ve happened?
This is a pretty painful thing to figure out the first time around, but it’s a pretty simple fix - OnServerEvent passes the player as the first argument.
This means your guiToDelete isn’t the GUI. You are deleting the player, because the events don’t care about the names of the values you pass, they just pass them in order with the Player always first. (The Player associated with the client that the FireServer() call originates from.)
The fix is as simple as adding a value to handle the player instance first:
My bad, I’m just now getting back into scripting. Even after doing so, it won’t delete the screen a second time around. If you keep pressing the prompt it will stack the clones and pressing the X will delete all those clones down to just one, and I have no idea why. Looking back on it, deleting the ScreenGui locally wouldn’t make any difference visually rather than deleting it on the server.
I see. The least confusing fix to implement here would just be to change the design and make the GUI handle deleting itself instead of searching for it, to be honest.
Instead of having to find the GUI just have the Local Script in the GUI listen for the close button and do something like:
if close signal received then
localscript.Parent:Destroy()
I’m no GUI expert, but aren’t all screen GUIs for players supposed to be in the player themselves, not server sided?
What would happen if you did all this with the this GUI loaded into a starter player GUI script?
Something has to change in the scripts because it works different when you activate it. I was thinking that the .Activated connection wasn’t disconnecting for some reason, but I don’t imagine it’s a bug with the engine so I have no idea.
I was thinking that every duplicate local script was firing every single time that the RemoteEvent fires, but the ScreenGui it’s parented to is destroyed so I don’t get how that could be. Something contradictory that I tested was putting a print statement after the script’s parent was destroyed, and it ran! Is the local script not closing/being destroyed?
If you are willing to change your approach, you can do the following to make the design less problematic.
Don’t clone the GUI into the Player every time and delete it. Instead, we would be changing the Enabled proprety of the ScreenGUI to make it invisible and inaccessible. Validate your ProximityPrompt interaction on the server and signal the client to flip the Enabled boolean instead in the Local Script (make it the opposite of what it is regardless of what it is).
This means that even if you spam the proximity prompt, all the GUI will do is switch between on and off instead of undergoing mitosis.
Then, add another behavior to the Local Script that will listen to the close button and disable the GUI when it’s clicked.
--LocalScript in StarterPlayerScripts
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local player = Players.LocalPlayer
local StartGameFolder = ReplicatedStorage:WaitForChild("StartGameFolder")
local StartGameGui = StartGameFolder:WaitForChild("StartGameGui")
local StartGameEvent = StartGameFolder:WaitForChild("StartGameEvent")
local activeGui
local function openGui()
if activeGui then
activeGui:Destroy()
end
activeGui = StartGameGui:Clone()
activeGui.Parent = player.PlayerGui
local exitButton = activeGui:WaitForChild("ExitScreen", true)
exitButton.Activated:Once(function()
activeGui:Destroy()
activeGui = nil
end)
end
StartGameEvent.OnClientEvent:Connect(openGui)
ServerScript
--ServerScript in ServerScriptService
local ProximityPromptService = game:GetService("ProximityPromptService")
local CollectionService = game:GetService("CollectionService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local StartGameEvent = ReplicatedStorage.StartGameFolder.StartGameEvent
for _, prompt in CollectionService:GetTagged("startgame") do
prompt.ObjectText = "Start game"
end
ProximityPromptService.PromptTriggered:Connect(function(prompt, player)
if CollectionService:HasTag(prompt, "startgame") then
StartGameEvent:FireClient(player)
end
end)
May need some more :WaitForChild()'s, was trying to be quick about it.
And I can’t test anything here😒. Tried to stick with your style.