Coroutine still running when paused?

Code:

local function round()

	while true do
		print("Still going!")
		if roundTime.Value > 0 then
			roundTime.Value -= 1
		else 
			res.Value = "Time ran out."
		end
			
		wait(1)
	end
end

local thread = coroutine.create(round)

start.Event:Connect(function()
	ended = false
	coroutine.resume(thread)

end)

res:GetPropertyChangedSignal("Value"):Connect(function()
	if res.Value ~= nil or res.Value ~= "" then
		print("Result changed, pausing...")
		ended = true
		ss:WaitForChild("Events"):WaitForChild("RoundResults"):Fire(res.Value, winners)
		coroutine.yield(thread)
		thread = coroutine.create(round)
		coroutine.yield(thread)
	end
end)

Context:
The event is only being fired once, but the coroutine’s still going. The “still going” prints even after the “result changed” prints. Why is it still going, and how can I stop it?

Thanks.

There’s no “thread” parameter to coroutine.yield()

I am pretty sure you can only pause a coroutine from inside the coroutine.

You can make a variable called “paused”, and make that when it’s true, you do coroutine.yield() within the thread (function).

Something like this:

local paused = false --Variable that'll determine the yield
local function round()

	while true do
		if paused then coroutine.yield()  end --Yield if pause is true
		print("Still going!")
		if roundTime.Value > 0 then
			roundTime.Value -= 1
		else 
			res.Value = "Time ran out."
		end
			
		wait(1)
	end
end

local thread = coroutine.create(round)
start.Event:Connect(function()
	ended = false
	coroutine.resume(thread)
	paused = false
end)

res:GetPropertyChangedSignal("Value"):Connect(function()
	if res.Value ~= nil or res.Value ~= "" then
		print("Result changed, pausing...")
		ended = true
		paused = true --Make the coroutine yield from insidess:WaitForChild("Events"):WaitForChild("RoundResults"):Fire(res.Value, winners)
		thread = coroutine.create(round)
		--the coroutine is yielded from inside as the variable is still true.
	end
end)
1 Like

There’s just one problem to that - it destroys the entire reason I used coroutines. I wanted the while true loop to instantly stop when the ended variable is set to true. (or just when the last part runs)

I made a module that eliminates this problem. You call wait() and it will wait until either the time you specified is up, or a condition is met. Here is the module.

local module = {}

function module.new()
	local self = setmetatable({},{__index=module})
	
	self.bypassWaits = false
	self.debug = false
	
	return self
end

function module:wait(amount,...)
	if amount > 0 then
		local waitEndsAt = os.clock()+amount
		local waitResult = "Waiting"
		while waitEndsAt > os.clock() do
			game:GetService("RunService").Heartbeat:Wait()
			local breakWait = false
			if self.bypassWaits then
				breakWait = true
			end
			for _,v in pairs({...}) do
				if v[1] == v[2] then
					breakWait = true
					break
				end
			end
			if breakWait then
				break
			end
		end
		if waitEndsAt > os.clock() then
			waitResult = "Timed Out"
		else
			waitResult = "Conditional Override"
		end
		return waitResult
	end
end

return module

To apply this to your code, and make it stop as instant as possible, just change your “wait(1)” to “module.new():wait(1,{paused,true})” The module interprets this line as "Wait until 1 second has elapsed, OR until the variable paused is set to true.

1 Like

It instantly stops it, as the while loop reaches the Paused if statement. Doesn’t it?

Well there’s a wait in the loop, so the changes won’t be instant.