Can't figure out how to do this timer

I’m stuck at a timer script, not just stuck but I got no idea on how to do what I want

So basically I wanted to do something like this:

  • make a tower defense game timer where it shows how many seconds left until next round

However, I cannot just make a normal timer with for loop. I need the timer to stop counting ONCE an event is fired ( skip wave event ), once the event is fired it starts counting again from a new value, kind of like abandoning the old timer.

I have no idea how to this, and also once the timer finished counting it returns. Do I use “coroutines?” or "events?"If so, how do I do this?

1 Like

add a check with a break event.

if(skip)then
break;
end;

I thought of that, however think of this:
I can’t change the values of other variables if a loop is running

local fired = false
local timeLeft = 60
-- setup your connection BEFORE the loop
event.OnServer/ClientEvent:Connect(function()
    fired = true
end)

while true do
    wait(1) -- your delay time/loop choice
    timeLeft-- -- take away 1 from the time left

    if fired then
        -- feel free to assign a variable and disconnect the event
        timeLeft = 60
        fired = false
    elseif timeLeft <= 0 then
        -- run your code if the timer is out
    end
end

I don’t think that method changes any variables, it just checks a pre-existing one.

warning: the code might have some slight issues/places where you need to edit, but it should lead you in the right direction

Yea but if the value is changed in the wait(1) then it will be delayed for a second and ruin the whole script and other scripts connected to it

I’m a bit confused. Are you saying that the code inside the loop will cause that delay, or that wait(1) is something you don’t want.

If you want, you can also do

event.OnServer/ClientEvent:Wait()

If you just wish to halt until it fired.

Not sure why you’ll need a timer that is crossed between context levels, what is the point?

--countdown timer, gets a numbervalue asset and decreases it until either the timer is 0 or destroyed
local function CountdownTimer(timerAsset: NumberValue)
	task.spawn(function()
		repeat
			task.wait(1)
			timerAsset.Value = math.max(0, timerAsset.Value - 1)
		until 
			(timerAsset == nil or timerAsset == 0)
		game.Debris:AddItem(timerAsset, 3)
	end)
end

--create a new timer for an object at a given path
local function NewTimer(path, startValue: number)
	if not path then
		warn("Must pass path for new timer's location.")
		return
	end
	if path:FindFirstChild("Timer") then
		warn("Path already has a timer. Cannot have 2 timers for the same object.")
		return
	end
	local timer = Instance.new("NumberValue")
	timer.Name = "Timer"
	timer.Value = startValue or 0
	timer.Parent = path
	CountdownTimer(timer)
	return timer
end

--convert timer to XX:XX string representation
local function ConvertTimerToString(timeValue: NumberValue)
	local min = math.floor(timeValue.Value / 60) 
	local sec = timeValue.Value - min*60
	local timeText
	if min < 10 then
		timeText = "0" .. tostring(min)
	else
		timeText = tostring(min)
	end
	if sec < 10 then
		timeText = timeText .. ":0" .. tostring(sec)
	else
		timeText = timeText .. ":" .. tostring(sec)
	end
	return timeText
end

Part of a time functions library I wrote.

It is a timer in a tower defense game where the timer is running and it has to be stopped suddenly when someone skips the wave or every single enemy is dead.
The point is I don’t know how to suddenly stop a running function and start a new one.

for example I changed the fired suddenly when someone skips the wave, if it’s that script then it will have to wait 1 second before doing something else. I don’t want that 1 second delay as it may affect other scripts’ timing and stuff.

Are you wanting to do something else inside the single script or on other scripts? If it’s inside that script, then you can use task.spawn(), if it’s for other scripts, I don’t think wait() effects scripts other than the one calling it.

ye but how do I stop the function suddenly anytime after task.spawn(), I know methods like doing checks inside the loop but the loop loops every 1 second and I don’t want a 1 second delay before checking

You can use task.cancel() to stop it, or simply break your loop when the condition is met and that will result in the thread of task.spawn() hitting the end of its stack. But that’s a fix to be used later.

Edit: Use the break method for now since task.cancel() is still unreleased. (Forgot it was still unreleased)

for i = 7, 0, -1 do --put your time start on "7"
		timer.Text = tostring(i)
		wait(1)
	end

I didn’t read through comments but I’ll just say this:

local RepS = game:GetService("ReplicatedStorage")
local NWT = RepS.NextWaveTime
local CT = RepS.CurrentTime
local Displaying = true

NWT.Changed:Connect(function()
  Displaying = false
  print("NEW EVENT")
  wait(1)
  Displaying = true
end)

while wait(0.4) do -- 0.4 seconds so it runs at least 2x per update. do maybe 0.9 so it checks at least once per update.
  local t = NWT.Value - CT.Value
  if t<0 then t = 0 end
  t = math.ceil(t)
  if Displaying then
    print(t)
  end
end

where NextWaveTime is a NumberValue representing when the next wave will come, and CurrentTime is a NumberValue representing the relative current time.