Introduction and Understanding
This is due to Filtering Enabled. Each Client runs this code locally—individually on their local machine. However, they all make requests to manipulate a ValueObject from the Server; the more Clients making subtraction requests, the further it's decrements increase.
To solve this issue, you must perform the arithmetic within a ServerScript. These programs do not run on the local machine but instead on ROBLOX's linked Server. The Server has replication priority, therefore any action it performs will be shown to all Clients within a singular operation.
We still need to somehow have the Client update it's UI in correspondence to the timer, so how do we link both the ServerScript and LocalScript together? This can be done using a specially designed Object called a RemoteEvent, that will allow us securely build a trusted communication between both ends.
Using it's method :FireAllClients(), and the RBXScriptSignal .OnClientEvent, we can tell it to ask the Client's to update their PlayerGui with the information passed.
Making the RemoteEvent:
This Instance need's to be available for both the Server and the Client connected, so we need to create this Object under ReplicatedStorage, a service that will transfer any information stored to both ends.
Getting to making our new ServerScript
It's of best practice to store Instance under their affiliated containers, thus, we should store a newly create Script within ServerScriptService. Let's get into the code:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RemoteEvent = ReplicatedStorage:WaitForChild("RemoteEvent")
local CountdownTime =
We start off with allocating all the necessary information into variables, notice how I use workspace instead of game.Workspace? There is a special keyword built for this container, it will allow us immediate reference to it. On another note, I use the :WaitForChild() method, this will tell the code to find the Object, and yield (wait) for it if it doesn't exist, this ensures no nil declarations in our variables.
SIDE-NOTE:
You may realize that Intermission is no longer declared, that's because it is not needed anymore. With the new code we'll be creating, the ValueObject will have no use anymore.
Let's get to re-creating the countdown:
for TimeLeft = CountdownTime,1,-1 do
local String = ("Intermission: %0x2d:%0x2d"):format(TimeLeft/60, TimeLeft%60)
RemoteEvent:FireAllClients(String)
wait(1) end
Note:
StackEdit is recognizing the special format syntax provided in the string concatenation above, this is a small issue that I'm unable to avoid. Please note that %0x2:%0x2 is not the authentic format syntax, please take the snippet from this pastebin that contains the real code for the String variable.
Whoa! Things got a little complicated there! It's time I explain! It's of best practice to use something called a for loop for numerical iteration. This loop will allow us to traverse over a set of instructions through a specified amount of time. This time is fed into a variable called TimeLeft, which is formatted to count down to 1 from (n) Time by 1 number. We then use a complex method of the String class called string.format(), which allows us to use special characters, to identify how we wish to push the information we supply into. We ask that it creates two 0-digit placeholders conjoined via a colon. This translates to 00:00. By then dividing the current number we're on by 60, we can get the minutes left, and by using the modulo % operator, we can get the remainder of the identical division, which returns the seconds left. The :format() method will push these calculations into 00:00 respectfully, giving us a proper digital-time effect.
Here is our finished ServerScript:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RemoteEvent = ReplicatedStorage:WaitForChild("RemoteEvent")
local CountdownTime =
for TimeLeft = CountdownTime,1,-1 do
local String = ("Intermission: %0x2d:%0x2d"):format(TimeLeft/60, TimeLeft%60)
RemoteEvent:FireAllClients(String)
wait(1) end
We're not done unfortunately, we still need to re-program our LocalScript. This shouldn't be too hard however, as all we need to do is declare the GUIObject that we wish to display the time for, and the same information for indexing the RemoteEvent.
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RemoteEvent = ReplicatedStorage:WaitForChild("RemoteEvent")
local Player = game:GetService("Players").LocalPlayer
local PlayerGui = Player:WaitForChild("PlayerGui")
local CounterGui = PlayerGui:WaitForChild("CounterGui")
local CounterFrame = CounterGui:WaitForChild("CounterFrame")
local Counter = CounterFrame:WaitForChild("Counter")
RemoteEvent.OnClientEvent:Connect(function(Time)
Counter.Text = Time
end)
If this helps, don’t forget to accept and upvote this answer! If you have any questions, feel free to comment below!
2 comments
because this script is getting copied to each player, which all subtract from the same value. so that means you have two or three scripts minusing from the same value., this would probably be the case if you were using a local script which im guessing you are because of the gui.
I am using a server script