Hello! I want to make a simple countdown that counts down from 10 to 0 using 0.1 intervals, however I don’t know what is the most efficient way to do it.
The countdown is being stored in a NumberValue.
I have tried using wait(0.1) in a loop but it takes longer than my desired 10 seconds (as shown in the gif below). https://i.imgur.com/tZ8FvoH.gif
Source code
local gui = script.Parent
local timer = gui:WaitForChild("Timer") -- TextLabel that shows the timer being updated by the while loop
local passed = gui:WaitForChild("10SecondsHavePassed") -- the TextLabel with the text "10 Seconds Have Passed" (as shown in the gif above)
local x = gui.Value -- the value with the countdown
function roundNumber(num, numDecimalPlaces)
return tonumber(string.format("%." .. (numDecimalPlaces or 0) .. "f", num))
end
spawn(function() -- this function enables a gui after 10 seconds have passed
wait(10)
passed.Visible = true
end)
while x.Value > 0 do
wait(.1)
x.Value = x.Value-.1
timer.Text = roundNumber(x, 1)
end
I have also tried to round using TweenService, which works but instead of incrementing by 0.1 it increments by a much smaller number, updating the NumberValue multiple times per second which halts performance. https://i.imgur.com/rRcAKC9.gif
Source code
local TweenService = game:GetService("TweenService")
local t_info = TweenInfo.new(10, Enum.EasingStyle.Linear)
local gui = script.Parent
local timer = gui:WaitForChild("Timer") -- TextLabel that shows the rounded timer based on the tween
local passed = gui:WaitForChild("10SecondsHavePassed") -- the TextLabel with the text "10 Seconds Have Passed" (as shown in the gif above)
local TimesRan = gui:WaitForChild("TimesRan") -- the TextLabel that shows the amount of times the value has been updated (as shown in the gif above)
local x = gui:WaitForChild("Value") -- the value with the countdown
local times_ran = 0
function roundNumber(num, numDecimalPlaces)
return tonumber(string.format("%." .. (numDecimalPlaces or 0) .. "f", num))
end
spawn(function()
wait(10)
passed.Visible = true
end)
local function test()
timer.Text = roundNumber(x.Value, 1)
end
x.Value = 10
TweenService:Create(x, t_info, {Value = 0}):Play()
x.Changed:Connect(function()
times_ran = times_ran + 1
TimesRan.Text = "Times ran - ".. tostring(times_ran)
test()
end)
As you can see, it updated 450 times when it should’ve updated 100 times, and when you have multiple of these countdowns in your game it starts to add up.
Any way I can make this update 100 times per second while still being exactly 10 seconds?
local function timer(t)
for i = t, 0, -task.wait() do
print(i)
end
end
Most implementations will have a similar efficiency but this is likely the shortest. Note this timer is dynamic as well (can be initiated from any desired start point).
local Time = 10
local Delta = tick() + Time
repeat
game["Run Service"].Heartbeat:Wait() --RenderStepped on the client for better results
warn(math.floor((Delta - tick()) * 100)/100)
until Delta <= tick()
Thank you for your response! Can you please explain a bit what the code is doing? I tried timer(10) and it spammed my output as shown below. https://i.imgur.com/DHfdhHy.gif
task.wait() returns the length of time elapsed during its wait, this returned value is subtracted from the timer in the for loop until the timer reaches 0.
I experimented a bit and found out that you can tween Integer values which does exactly what I want.
Here is the source code with an example for any one interested or anyone in the future who has the same problem as me: https://i.imgur.com/4mmd1QM.gif
local tmp = game:GetService("ReplicatedStorage"):WaitForChild("$temp") -- temporary folder
local TweenService = game:GetService("TweenService")
local instance = Instance.new("IntValue", tmp)
local countdown = nil
local function StartCoundown(timer)
warn("Starting! cooldown")
local t_info = TweenInfo.new(timer, Enum.EasingStyle.Linear)
instance.Value = timer*10
countdown = TweenService:Create(instance, t_info, {Value = 0})
countdown:Play()
end
local function PauseCountdown()
warn("Pausing cooldown")
if countdown then countdown:Pause() end
end
local function ResumeCountdown()
warn("Resuming cooldown")
if countdown then countdown:Play() end
end
local function StopCountdown()
warn("Stopping cooldown")
if countdown then countdown:Pause() end
countdown = nil
instance.Value = 0
end
local function PrintTimer()
print(tonumber(instance.Value)/10)
end
instance.Changed:Connect(PrintTimer)
StartCoundown(10)
wait(10)
print("10 seconds have passed!")
And yes, I added methods so you can resume/pause/stop the countdown as you wish.
Does using intValue or boolValue cause the same problem?
When I play a game with 20 players, the count sometimes disappears. This method seems to be using the client. Are you exposed to the same time as others?