I’m making a game where GUIs are needed, but I’m having trouble deciding if I want them to run on the server or client.
Running them on the server is easier, as I can control them from a single server script instead of a server script and a local script, but running them on the client will make the game faster.
Running them on the client, though, is less secure because you need to fire RemoteEvents, which can be faked.
So, running them on the server is easier and secure but laggier, while running them on the client is less secure but improves server performance. Server = secure but lag, client = faster but not as secure.
Which one is better to run GUIs on?
Also, another question, GetNetworkOwner is a function of BasePart, but is there a function to use this on GUIs? If there was, that would also be better.
There is never an instance where you should run GUIs on the server - ever. It is not supported behaviour by Roblox and you’ll immediately start hitting walls. The only real exception to these may be the world-space interfaces (i.e. SurfaceGuis and BillboardGuis) - but even then, it’s rarely the case that it is better to run it on the server.
It might be easier in the short term, but in the long term it’s easier to code your game more securely, efficiently and in line with Roblox’s guidance by running your interfaces & effects locally, and your business logic on the server.
In regards to what you said about RemoteEvents, I’m not sure what you mean that they can be faked. Yeah, they can be used by exploiters in the same way you can use them in your own Local Scripts - but I’m not sure why sending data directly from server → client via :FireClient would allow an attacker to inject malicious data into the server, or other clients. It is not more secure to do interface work on the server.
Unfortunately, I am only able to partially understand what you are saying.
[using first quote] I believe you that you are advising me not to trust the client, and [using second quote] run GUIs on the client, but always check with the server when needed, meaning I need to use scripts, local scripts, and remote events.
(My statement above may counteract itself because the two quotes confuse me.)
Okay, I can understand that more, but I need to count all the player’s votes when they vote maps for a round. How would I do that if I run GUIs on the client?
I’m guessing you’re saying that GUIs properties such as size and Visible should be configured on the client, and other things not relating to GUIs like vote counting should be sent to the server.
The LocalScript would listen to Button press events (MouseButton1Click) on the TextButtons in your ScreenGui for voting. It would then send that vote over to the server via the RemoteEvent. The server would then use FireAllClients to send the updated Vote tally over.
Here is some pseudocode to illustrate better:
-- Client.lua
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RemoteEvent = ReplicatedStorage:WaitForChild("VoteRemoteEvent")
local ScreenGui = script.Parent
local VoteButton = ScreenGui:WaitForChild("VoteButton")
local CurrentVotes = ScreenGui:WaitForChild("CurrentVotes")
-- This is a Frame that you show all the voter info
local function UpdateVotes(VoteInfo)
for Player, Vote in pairs(VoteInfo) do
-- Update your UI
end
end
Event.OnClientEvent:Connect(UpdateVotes)
VoteButton.MouseButton1Click:Connect(function()
-- Let's pretend they voted for Map "A"
Event:FireServer("MapA")
end)
-- Server.lua
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerStorage = game:GetService("ServerStorage")
local RemoteEvent = ReplicatedStorage:WaitForChild("VoteRemoteEvent")
local VoteInfo = {}
local Maps = {
["MapA"] = ServerStorage:FindFirstChild("Map A")
}
Event.OnServerEvent:Connect(function(Player, Map)
if Maps[Map] then
VoteInfo[Player.Name] = Map
end
Event:FireAllClients(VoteInfo)
end)