Accessing PlayerGui on the Server Side

I have been accessing the player’s PlayerGui through server scripts but have been receiving errors with both FindFirstChild() and WaitForChild() when accessing certain elements within it. Is there a better method/workflow for getting a player’s PlayerGui on the server side?

Thanks! :smiley:

2 Likes

GUIs located within StarterGui can be accessed by the Server. Because StarterGui is cloned by the Server and Client.

The only time you’ll have problems is when client takes GUI from ReplictatedStorage (or somewhere) and clones it to their PlayerGui. The Server will not see that replication of the Gui.

An option could be having the server cloning GUI for the players.t.

you don’t. there’s not a single time you should ever do this.

Maybe it could be a specific object value that is linked to playergui you link that object value for once then you can use it everytime when you want I don’t know any ohter method

1 Like

This is my current method but it has a lot of issues when the player joins initially.

What kind of issues I don’t get issues when i access to playergui from server

If I wanted to make a button that when clicked gives a player money, I would have to use a RemoteEvent if the code was on the client side. The RemoteEvent is subject to being manipulated, which is why I choose to handle Gui on the server side. Is there a better way to do this on the client while avoiding possible security flaws?

Mostly just replication. For some players, the server sometimes has trouble identifying replicated objects. I wanted to know if there was a better method to handling this situation.

sadly i don’t know if there is better solution

You should check and confirm every remote event arguments coming through from client side then it couldn’t be manipulated

Handling gui on the server won’t change anything as it can still be manipulated. You need to run checks on the server regardless.

Not only is accessing gui from the server bad practice, it’s incredibly unreliable. Gui are often subject to a lot of change during runtime and any change made on the client won’t be replicated to the server. Also the server can not access your gui if ResetOnSpawn is enabled.

1 Like

You shouldn’t pass important information through RemoteEvents anyway, imagine a case where a player purchases an item through clicking a button, which fires a RemoteEvent, you wouldn’t get the price of this item through the client, you would have an identifier that is given from this RemoteEvent which you check for its corresponding data of to get the price of the item.

For your server-side button press, you now obtain the same information from the instance. Which is less convenient, but uses the same underlying logic.

1 Like

Add a debounce on the server side if you want to avoid spamming. You should specify what you want to exactly do or avoid.

Agreed, I think this might be a case of the XY problem. Tech_Voyager, do you think you could describe what your end goal is?

I was mostly looking for the best way to declare objects when a player joins while avoiding common errors. I have a lot of issues with doing this with players that have varying internet connection strengths.

I noticed I was a little unclear about that in my original messages, sorry about that!

1 Like

As mentioned earlier, when a player joins, and if you already have items located in StarterGui, the server and client replicate those objects to a players PlayerGui. The client and the server have access to the same objects. The client will take a second to download those objects, but the server will have them first.

The server can call Player.PlayerGui.GuiNameHere or use FindFirstChild(“namehere”). The server does not need to do WaitForChild in this instance.

The client may have to do :WaitForChild(“guinamehere”) because they may not have downloaded everything yet.

My server scripts for PlayerGui look something like this:

game.Players.PlayerAdded:Connect(function(player)
     local Gui = player.PlayerGui:WaitForChild("Gui")
     local Frame = Gui:WaitForChild("Frame")
     local TextButton = Frame:WaitForChild("TextButton")

     TextButton.Text = "Hi"
end)

Because the server already has access to the objects, would using WaitForChild() not be necessary?

My full setup utilizes ModuleScripts so it would look something like this:

Server Script:

game.Players.PlayerAdded:Connect(function(player)
     Module.ModuleScript(player)
end)

Function in ModuleScript:

function Module.ModuleScript(player)
     local Gui = player.PlayerGui:WaitForChild("Gui")
     local Frame = Gui:WaitForChild("Frame")
     local TextButton = Frame:WaitForChild("TextButton")

     TextButton.Text = "Hi"
end

Does the same thing apply?

You can simply do:

function Module.ModuleScript(player)
     local Gui = player.PlayerGui.Gui
     local Frame = Gui.Frame
     local TextButton = Frame.TextButton

     TextButton.Text = "Hi"
end

-- OR

function Module.ModuleScript(player)
     local Gui = player.PlayerGui:FindFirstChild('Gui')
     local Frame = Gui.Frame
     local TextButton = Frame.TextButton

     TextButton.Text = "Hi"
end


Remember, FindFirstChild… and FindFirstAncestor… both have multiple “options” to choose from, such as, OfClass, or WhichIsA when you go into programming UI.

With the Connections, if you don’t plan to add any additional code to this PlayerAdded event, I’d recommend doing…

game.Players.PlayerAdded:Connect(Module.ModuleScript)

The Player argument will be passed along