Is this a good way to make a countdown?

I made a countdown system, but I don’t know if this is a good way to do so.

local Run_Service = game:GetService("RunService")

local Cooldown_Frame = --This instance's location isn't important

local Run_Time = 10

local Connection

Connection  = Run_Service.Heartbeat:Connect(function(Delta_Time)

	if Run_Time <= 0 then

		Connection:Disconnect()

		print("Done!")

	else

		local Cooldown_Number = math.round(Run_Time * 10) / 10

		Cooldown_Frame.Text = "Cooldown: "..Cooldown_Number

		Run_Time -= Delta_Time

	end

end)
1 Like

Just wondering the reasoning behind using RunService? When the exact same thing can be solved with a for loop.

local Run_Time = 10
for i=Run_Time, 0, -1 do
    Cooldown_Frame.Text = "Cooldown: "..Cooldown_Number
    task.wait(1)
end

Unless you have a reason to be checking stuff every frame, I generally would recommend not using Heartbeat.

1 Like

I’m trying to make the timer as accurate as possible, “task.wait()” has proven to be ineffective due to always delaying by a frame (about 0.0167 seconds), as an example, using it 60 times would increase the actual countdown time by an entire second, so RunService seemed to be a good option for accuracy.

2 Likes

Your code looks fine overall, only thing I would suggest is checking if the Cooldown_Number isn’t the same as the last one if you’re gonna be adding more code later on like visual effects.

local Last_Count = 0 -- add before event

if Cooldown_Number ~= Last_Count then
	Last_Count = Cooldown_Number
	Cooldown_Frame.Text = "Cooldown: "..Cooldown_Number
	-- other code
end
1 Like

You’re already rounding to the tens place which means going beyond 1/60th isn’t a concern. You can use task.wait() for this.

1 Like

For improved comprehension, contemplate using an identifiable constant in place of a magic number, such as 10 in math.round(Run_Time * 10) / 10.Moreover, for coherence, I advocate using camelcase.

1 Like

I’m actually rounding so that the countdown can show decimals too, if I didn’t want decimals then I wouldn’t have to worry about the task.wait() delay, as it would be very unnoticeable.

-- Let's suppose that the current "Run_Time" is 3.333

-- 3.333 * 10 = 33.33
-- 33.33 (rounded) = 33
-- 33 / 10 = 3.3

print(math.round(Run_Time * 10) / 10) -- This would print "3.3"
1 Like

Also, forgot to mention this, but “task.wait()” always delays by a frame, so “task.wait(2)” actually waits for something around 2.0167 seconds instead of 2 seconds.

1 Like

Check out this video. Very well explained and shows exactly what you are looking for

1 Like

You can still use a while loop. Just keep track of the tick() of when the timer started. Use an empty task.wait() and update the text to the difference between the current and initial tick(). Use a math.round() to help out that readability.

If you still don’t want to use a while loop with task.wait(), replace task.wait() with RunService.Heartbeat:Wait() to get the same effect.