Coroutine.create and coroutine.resume seem not to be working

Hello!

I’m trying to make a timer for multiple people, using coroutines. Not sure what else to add.

Here’s my script:

local RS = game:GetService('ReplicatedStorage')
local event = RS.Remotes.SendTimerData
for i,v in pairs(workspace.Teleporters.TowerTeleporters:GetChildren()) do
	v.Touched:Connect(function(hit)
		if hit.Parent:FindFirstChild('Humanoid') then
			local plr = game.Players:GetPlayerFromCharacter(hit.Parent)
			local timerCoroutine = coroutine.create(function()
				local zero = 0
				while true do
					for i = 0, math.huge do -- mins
						for i2 = 0, 59 do -- secs
							for i3 = 0, 9 do -- 1/10 secs
								local min, sec, ms
								if i <= 9 then
									min = zero..i
								else
									min = i
								end
								if i2 <= 9 then
									sec = zero..i
								else
									sec = i
								end
								if i3 <= 9 then
									ms = zero..i
								else
									ms = i
								end
								local timeToSend = min..':'..sec'.'..ms
								print(timeToSend)
								event:FireClient(plr, timeToSend)
								wait(0.1)
							end
						end
					end
				end
			end)
			coroutine.resume(timerCoroutine)
		end
	end)
end

TIA for any help!

Hello, below I’ve created a basic example of a coroutine:

function testFunction(TestParam) --Function for Coroutine to run
	while true do
		print(TestParam)
		wait(1)
	end
end

for i = 1, 10, 1 do
	--Creating the Coroutine
	local timerCoroutine = coroutine.create(function()
		testFunction(i) --Calls the function the Coroutine should run
	end)
	
	coroutine.resume(timerCoroutine) --Starting the Coroutine
end

This is how I would structure them when writing the code. I could be wrong but you may want to check your code logic as if you start a new coroutine each time someone touches the part, what happens if the same person touches the same part twice.

As I said above, I may be reading this incorrectly however I think it would start two coroutines for the same person which would be firing multiple events to the client with different timers?

Anyway, Hope this helps :slightly_smiling_face:

1 Like

Yeah, I plan on adding a debounce, however I wanted to create a single coroutine which would be stopped whenever they press the end part. I’m pretty new to coroutines so I’m not sure where to go from here. Wouldn’t your example create 10 coroutines though?

I’ll try to reformat my script closer to yours and let you know.

Eh, yeah you’re correct :slightly_smiling_face:, for your case you would remove the for loop.

My personal choice is to put the functionality in a separate function just to separate the code a little bit.

Yeah a denounce should work fine for this I think.

You’re definitely along the right lines, just keep in mind that once the coroutine is started, if it has a while true do in it then it will run continuously.

1 Like

I’m not sure if it’s the coroutine.create or resume that’s doing it, however it isn’t working. I updated it to be a bit closer to yours, I’ll put it below.

I also added a print in the .Touched function and it is being printed.

local RS = game:GetService('ReplicatedStorage')
local event = RS.Remotes.SendTimerData

local function calculateTime(plr)
	local zero = 0
	while true do
		for i = 0, math.huge do -- mins
			for i2 = 0, 59 do -- secs
				for i3 = 0, 9 do -- 1/10 secs
					local min, sec, ms
					if i <= 9 then
						min = zero..i
					else
						min = i
					end
					if i2 <= 9 then
						sec = zero..i
					else
						sec = i
					end
					if i3 <= 9 then
						ms = zero..i
					else
						ms = i
					end
					local timeToSend = min..':'..sec'.'..ms
					print(timeToSend)
					event:FireClient(plr, timeToSend)
					wait(0.1)
				end
			end
		end
	end
end

for i,v in pairs(workspace.Teleporters.TowerTeleporters:GetChildren()) do
	v.Touched:Connect(function(hit)
		if hit.Parent:FindFirstChild('Humanoid') then
			local plr = game.Players:GetPlayerFromCharacter(hit.Parent)
			local timerCoroutine = coroutine.create(function()
				calculateTime(plr)
			end)
			coroutine.resume(timerCoroutine)
		end
	end)
end

Hmm, seems fine to me. Try putting a print into the coroutine. see if it even gets started.

1 Like

Yeah, I added a print and it does seem to be starting. Must be an error with my script, but I am not sure what’s wrong with it as it seems to work outside of a coroutine.

I think the easiest way to test this is to put prints every 3 lines and see where it gets stuck. Also put a print on the receiver for the FireClient Call and see if the client is receiving it.

1 Like

Stops at g.

local function calculateTime(plr)
	print('cor started')
	local zero = 0
	while true do
		print('a')
		for i = 0, math.huge do -- mins
			print('b')
			for i2 = 0, 59 do -- secs
				print('c')
				for i3 = 0, 9 do -- 1/10 secs
					print('d')
					local min, sec, ms
					if i <= 9 then
						min = zero..i
					else
						min = i
					end
					print('e')
					if i2 <= 9 then
						sec = zero..i
					else
						sec = i
					end
					print('f')
					if i3 <= 9 then
						ms = zero..i
					else
						ms = i
					end
					print('g') -- stops here, g is being printed
					local timeToSend = min..':'..sec'.'..ms
					print(timeToSend)
					print('h')
					event:FireClient(plr, timeToSend)
					wait(0.1)
				end
			end
		end
	end
end

resume returns a boolean along with the result of the coroutine or an error message. I suspect there’s an error in the body of your callback function and resume is suppressing it. If you want errors to be thrown, you should use wrap instead.

local resumeCallback = coroutine.wrap(function ()
  ...
end)

local result = resumeCallback()

otherwise, you can do:

local thread = coroutine.create(function ()
  ...
end)

local success, result = coroutine.resume(thread)
if not success then
  warn("Callback error:", result)
end

Fun-fact. You can actually pass arguments directly to a coroutine.

local function myCallback(a, b, c)
  print(a, b, c)
end

local resume = coroutine.wrap(myCallback)
local result = resume(1, 2, 3)

-- or

local thread = coroutine.create(myCallback)
local success, result = coroutine.resume(thread, 1, 2, 3)
1 Like

I forgot 2 periods, that was the problem.

Nice. Good Luck with your project :slightly_smiling_face:

Also @woot3, Thanks for this. Good work

1 Like