Trouble destroying a GUI created on the client from the server

Hello all, thanks for taking the time to read my post. I want to achieve something very simple. In my game, there is a GUI which is cloned from replicated storage via the client, and I am attempting to destroy it from the server.

For some context, I wanted to make a simple “Get Rich Tycoon”-esque game for fun, and the main source of early money generation is panhandling, or asking strangers for money. I managed to create a working system, but I only want the player to be able to ask a specific person ONCE, without having any of the planned upgrades to change that.

Here is a video which demonstrates the system:

example.wmv (2.3 MB)

As you can see, in the video, I can click the cloned GUI multiple times, and I do not want that to be the case.

For context, here are some scripts which show the process.

This triggers on the proximity prompt, and creates the gui shown atop the screen when seated:
LocalScript:

GUIEvent.OnClientEvent:Connect(function(player)
	local pName = Players.LocalPlayer.Name
	local localP = Players.LocalPlayer.PlayerGui
	PlayerMovement:Movement(player, false)
	local newGui = GUI:Clone()
	newGui.Parent = Players.LocalPlayer.PlayerGui
	newGui.Name = game.Players.LocalPlayer.Name
	spawner:spawn(localP, pName)
end)

Here is the script for the TextButton that appears above the NPC, which is used to gain money:
LocalScript:

local player = game.Players.LocalPlayer

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local event1 = ReplicatedStorage.PanhandleMoney:FindFirstChild("RemoteEvent1")

local button = script.Parent

local function activateButton()
	event1:FireServer(player)
end

button.Activated:Connect(activateButton)

The Server Script that the above remote event connects to:

event1.OnServerEvent:Connect(function(player, name)
	local playerProfile = profileCache[player]
	
	if playerProfile.Data.panhandleUpgrades.guiUpgrades.clickTwice == false and playerProfile.Data.panhandleUpgrades.guiUpgrades.clickThrice == false then
		local randomInt = tonumber(tostring(Random.new():NextNumber(0, 3)))
		playerProfile.Data.Money+=randomInt

		local formattedMoney = string.format("%.2f", randomInt)
		pMoney:createGUI(player, formattedMoney)
	end
end)

I have tried various solutions. My original idea was to simply add the following line of code at the end of the above server script (after “pMoney:createGUI…”)

player.PlayerGui:FindFirstChild("NPCWalk1GUI"):Destroy()

NPCWalk1GUI is the name of the gui I want to be destroyed. I also tried “WaitForChild” instead of “FindFirstChild”. This is when I figured out that this would not work because the GUI was created using the client. To test this hypothesis, I added the below code to the same if statement, and sure enough, the GUI I want to destroy was not printed.

	for _, gui in player.PlayerGui:GetChildren() do
		print(gui)
	end

After this, I assumed I would have to destroy the GUI from the client, and this is where I am struggling to find a solution. I recently tried connecting a server to client event from the above already established remote event. It appeared right below “pMoney:createGUI…”

singleEvent:FireClient(player)

I connected the event in a LocalScript as follows:

singleEvent.OnClientEvent:Connect(guiDestroy:basicNPCWalk1(Player))

In order to not cloud my game with RemoteEvents, I was hoping to connect the event to a modulescript, and use this last line of code for whenever I want to destroy a GUI.

In a ModuleScript:

player.PlayerGui:WaitForChild("NPCWalk1GUI"):Destroy()
-- FindFirstChild was also tried.

I am fairly certain I did this wrong, so any advice to this issue is greatly appreciated. Thanks again for taking the time to read this post.

The only way you can do this is firing a remote event since the GUI won’t exist on the server. If something is created on client, server can’t see it.

Yeah, I actually found a way to get it to work with both a ModuleScript and a separate remote event. I think the reasons I was having trouble was due to my inability and lack of knowledge to code…

If anyone ever has an issue similar to this, here is how I got it work with a ModuleScript & Remote Event.

In a ModuleScript:

function guiDestroy:basicNPCWalk1(localP)
	repeat
		wait(.1)
	until localP.PlayerGui.NPCWalk1GUI
	localP.PlayerGui:WaitForChild("NPCWalk1GUI"):Destroy()
end

And a RemoteEvent in a LocalScript:

local function guiDestroyer()
	guiDestroy:basicNPCWalk1(localP)
end
singleEvent.OnClientEvent:Connect(guiDestroyer)

But still, your above point rings true. It can only work with a remote event. I only wanted to use a ModuleScript in the first place because I saw a post one time on this site which said if you utilize ModuleScripts correctly, you can realistically use only a single remote event for a single game. I wanted to practice that technique.