Moving folder in client with data to Workspace

I’m creating a game where a player creates a bunch of GUI frames on their screen and once they press a GUI button, all the GUI frames on their screen get copied and put into a SurfaceGui in game.Workspace.

The user starts with an empty folder in their PlayerGui and Gui frames gets added into that folder.

A solution I was thinking was to use a RemoteEvent and have the client send the folder full of Guis to the server, but the problem is that when I use RemoteEvents with a folder with descendants, it only copies the folder and nothing inside it; basically it is as if when the script is being read at “compile time” it only sees that object at the moment and does not ever update itself.

Thanks in advance!

What do you mean by this? Is the player creating these GUIs themself dynamically? Or are they just GUIs created by you that are first inside the PlayerGui, and then you want to copy them out to replicate to all clients on a SurfaceGui.

You have the right idea, except you got it backward. The client should ask the server to copy its GUIs into workspace. The server should be able to clone the GUIs from their PlayerGui and parent them to workspace.

It’s a drawing game so the GUIs are created by me (circles) and then the user can dynamically add circles on a canvas to create the drawing aspect. All the circles are in a folder in PlayerGui and I just want to move the folder and all of its descendants to Workspace.

I’m doing client to server using FireServer() and OnServerEvent() with the folder being passed in as a parameter, but when time comes to use the functions, it only gets the empty folder with no Gui frames added to it by the client.

In the client’s data, I can see all the Gui frames, but only the folder with no Gui frames gets copied to the server.

You can’t replicate objects like that directly through a RemoteEvent. You will need to request (ask) the server to do the copying on behalf of the client. So instead of passing a folder directly, you will instead pass a value that instructs the server what it will be looking for to copy.

Note: this should be validated by the server to prevent an exploiter from firing the remote and making the server potentially copy malicious things to the server…

Here is a pseudocode example:

Client Script

local player, button = ...

local requestGuiCopyEvent = game.ReplicatedStorage.RequestGuiCopy

button.MouseButton1Click:Connect(function()
	local guiToCopy = player.PlayerGui.Canvas.Circles
	requestGuiCopyEvent:FireServer(guiToCopy.Name) --pass the server the name, so it can look for it itself
end)

Server Script

local requestGuiCopyEvent = game.ReplicatedStorage.RequestGuiCopy

requestGuiCopyEvent.OnServerEvent:Connect(function(player, guiName)
	local canvas = player.PlayerGui:FindFirstChild("Canvas")
	local guiToCopy = canvas and canvas:FindFirstChild(guiName)
	--probably do some more validation...
	if (guiToCopy) then
		local guiClone = guiToCopy:Clone()
		guiClone.Parent = workspace
	end
end)

An alternative solution is to send raw data over the event about the circles so the server can reconstruct them from brand new (this is technically safer and allows for better validation and protection against exploits).

Thanks for the insight! I’m considering using a for loop for each circle drawn now and I’m going to reconstruct them. Will take a lot of restructuring but hopefully it will be worth it.