Is it bad to control stuff in a server-script

  1. What do you want to achieve? I am trying to make it where when you press a click detector it adds 1 to a gui text (e.g: 1,2,3,4,5,6 incrementing each time you click)

  2. What is the issue? Everything works fine but im not sure if its bad practice to use a server script to detect the click, tween the text, and update the text. Should I use a remote event and local script or something, or is this fine?

  3. What solutions have you tried so far? Did you look for solutions on the Developer Hub?

local clickDetector = script.Parent.ClickDetector

local counter = script.Parent.SurfaceGui.Counter.Counter

local tweenService = game:GetService("TweenService")

local tweenInfo = TweenInfo.new(.05,Enum.EasingStyle.Quart,Enum.EasingDirection.InOut,0,true)

local clickBounce = tweenService:Create(counter,tweenInfo,{

Rotation=math.random(-10,10)})

function onMouseClick()

counter.Text += 1

clickBounce:Play()

end

clickDetector.MouseClick:connect(onMouseClick)
1 Like

Yes, this is bad practice. User interface things should be handled on the client side to make them as smooth as possible. If I had to take a guess, you are testing inside of studio, which by default has 0 ping.

If you need to store the number of clicks on the server, then you would also fire a remote event to inform the server that you pressed the button. You could then either have this update an IntValue object or fire another remote event to all of the clients with an updated count of the number of clicks.

As for the client sided code, you would immediately update the local number of clicks by adding 1 to it and then updating the gui. Upon receiving an event from the server indicating a new number of clicks, you would simply compare the existing number to the new number, and take the maximum of the two.

Hopefully that makes sense.

4 Likes

It really depends on the use case for the UI, if the UI is to be shared by everyone then handling it inside a server script is perfectly fine. When UI becomes unique to individual players then it should be handled through the use of RemoteEvents & local scripts. After further inspection it appears the original poster likely wanted the UI to reflect differently for each player so your solution is correct.

1 Like

SurfaceGui’s are still part of the user interface. That is why they are setup such that you have to put them in the PlayerGui and Adornee them to the world space.

Additionally, with high ping, the player will run into the problem I hinted at, which is that handling it on the server will cause unnecessary lag. While this works fine in testing, for production quality code this is both bad practice and will result in the worst user experience.

This is actually incorrect, it should not take 2000ms for a person with 1000 ping to receive interface updates, regardless of whether or not only they can see it or anyone can see it, and regardless of whether or not it is in the world. Especially when you can make it take ~0ms.

In the case that the counter should be different for each user, remote events should not be used whatsoever except for tracking purposes.

Check the last comment I edited into the post.

1000 ping ~= 2000ms, 1 ping directly converts to 1 millisecond of latency, and if you’re relying on a server script & RemoteEvents then lag will still be present.

The 2000ms refers to the RTT, in which it takes 1000ms for an update from the client to reach the server, and then 1000ms to return the updates back to the client. As such, if a user has 1000 ping it will take 2000ms to receive the updated counter value when the client clicks the button.

You’re right, for this case the server script is relying on a button click before responding, in the case that the server script is constantly updating the UI, the latency would only be observed at 1000ms. The 2nd argument still stands, lag will still be present when relying on the use of server scripts & RemoteEvents.

Furthermore if a UI is to be shared by all players (consider a timer for example), it is fine for it to be managed solely through the use of a server script, since its intended to reflect the same for all local players.

UI state management should still not be handled by a server script, whether it is for read-only information or not.

I’ll also explain why a timer (which is being displayed) should not be handled by the server

  • It adds additional bytes to the packets sent by the server every physics update (assuming there is a delta change on the timer that update)
  • It has additional latency and isn’t exactly reliable. Especially since we have the ability to know the server time at any given moment with workspace:GetServerTimeNow(), and we can just base the timer on the initially provided server time. Thus having no latency issues and resulting in a timer that perfectly syncs over all clients.

No? I just acknowledged that in my reply.

You’re right, for this case the server script is relying on a button click before responding

I was describing a different scenario in which the server is constantly updating the client regardless of the client’s actions.

This post is devolving into arguments bordering on semantics.

A click detector is fine to handle on the server, provided the SurfaceGui exists inside that part anyways, it will replicate automatically.

I’m not sure where the notion came from that you’re passing UI changes to the client.

Thanks, this is what I was trying to get across, a server script is fine for UI which is shared by all players (and none of the UI pertains to a single player uniquely).

It’s a kind of interesting problem. While it isn’t a problem to handle a counter using a server script for testing purposes, it is definitely not production quality. At which point you could make the argument that is is technically “bad” to control it in a server-script, which is relevant to the OP’s original question.

The reason you are passing UI changes to the client is because you are updating a global counter, and then telling the client to display said global counter. If you do this without using an Adornee, and instead opt to use a server-script, you are having Roblox handle this for you, and as a result lose some control over how this process occurs. On the other hand, if you hard-code it and handle the SurfaceGui by putting it into the PlayerGui and Adorneeing it to the world space, you gain full control over the replication of said counter.

Immediate feedback when performing an action in-game (clicking, pressing a button, etc) is important to create a good user experience. If you can see an update instantaneously on a server-wide counter, even when you have 1000 ping, it will be more enjoyable than having to wait 2 seconds to see your update.

In OP’s use case, there is no production quality problem with incrementing on the server. Handling an event that the server detects, on the server, is not inherently bad, and depending on your organizational practices can avoid extra remote clutter.

I see nothing wrong with either solution.

1 Like