After the coroutine prints “Yielding”, it yields once, and after that, it does nothing, and after that, it is dead, because there is nothing else to run.
One thing you should definitely keep in mind when dealing with coroutines in this manner, is that yielding functions… you know… yield. wait()
will actually call coroutine.yield
(after telling the thread scheduler to resume this thread later). This means the second print(coroutine.status(coroutineLoop))
in bindableFunction.OnInvoke(variable)
will run immediately after the first wait(0.1).
It’s also possible to make a thread wait (with wait()
) and resume it mid-wait, which will make wait() return early, return whatever you resumed the thread with instead of the time taken (I think. I haven’t tried it) and the thread will be resumed again by the thread scheduler, most likely when it’s already dead (which makes it error) or when it really shouldn’t be resumed.
Here is the code with lines annotatated:
--[[A1]]bindableFunction = game.Workspace.Function
--[[A2]]bindableFunctionVariable = bindableFunction:Invoke("randomVariable")
--[[A3]]wait(2)
--[[A4]]bindableFunctionVariable = bindableFunction:Invoke("randomVariable")
--[[A5]]wait(2)
--[[A6]]bindableFunctionVariable = bindableFunction:Invoke("randomVariable")
--[[B1]]coroutineLoop = coroutine.create(function(someVariable)
--[[B2]] print(someVariable)
--[[B3]] for i = 1,10 do
--[[B4]] wait(0.1)
--[[B5]] end
--[[B6]] print("Yielding")
--[[B7]] coroutine.yield()
--[[B8]]end)
--[[C1]]function bindableFunction.OnInvoke(variable)
--[[C2]] print(coroutine.status(coroutineLoop))
--[[C3]] coroutine.resume(coroutineLoop, variable) --the second time resuming the coroutine, it seems to kill it.
--[[C4]] print(coroutine.status(coroutineLoop))
--[[C5]] wait(1)
--[[C6]] print("SomethingRandom")
--[[C7]] wait(2)
--[[C8]] return
And here is the exact path I think the code takes:
--[[A1]]bindableFunction = game.Workspace.Function
--[[A2]]bindableFunctionVariable = bindableFunction:Invoke("randomVariable")
--[[C2]] print(coroutine.status(coroutineLoop))
--[[C3]] coroutine.resume(coroutineLoop, variable)
--[[B2]] print(someVariable)
--[[B3]] for i = 1,10 do
--[[B4]] wait(0.1) -- coroutine. will yield immediately, going back to the main thread but being promised to be revived in 0.1 seconds
--[[C4]] print(coroutine.status(coroutineLoop)) -- main thread. remember, this happened immediately
--[[C5]] wait(1) -- main thread yields. now all threads are sleeping, waiting to be resumed
------------~0.1 seconds pass
--[[B4]] wait(0.1) -- coroutine. resumed by thread scheduler 0.1 seconds after the for loop was first entered
------------~0.1 seconds pass
--[[B4]] wait(0.1)
------------~0.1 seconds pass
--[[B4]] wait(0.1)
------------~0.1 seconds pass
--[[B4]] wait(0.1)
------------~0.1 seconds pass
--[[B4]] wait(0.1)
------------~0.1 seconds pass
--[[B4]] wait(0.1)
------------~0.1 seconds pass
--[[B4]] wait(0.1)
------------~0.1 seconds pass
--[[B4]] wait(0.1) -- this is nine wait()s, not ten - it's possible, but astronomically unlikely that all ten wait()s will run in the span of that wait(1), because I'm fairly sure the thread scheduler likes to run late, not early
------------indeterminate amount of seconds pass
--[[C6]] print("SomethingRandom") -- main thread resumed by thread scheduler after that wait(1)
--[[C7]] wait(2) -- main thread yields
------------indeterminate amount of seconds pass
--[[B4]] wait(0.1) -- coroutine. resumed by thread scheduler
------------~0.1 seconds pass
--[[B6]] print("Yielding")
--[[B7]] coroutine.yield() -- coroutine yields to thread scheduler. thread scheduler does nothing
------------ a good bit less than 2 seconds pass
--[[C8]] return -- main thread resumed after 2 seconds
--[[A3]]wait(2) -- main thread yields again. coroutine is still sleeping
------------~2 seconds pass
--[[A4]]bindableFunctionVariable = bindableFunction:Invoke("randomVariable")
--[[C2]] print(coroutine.status(coroutineLoop))
--[[C3]] coroutine.resume(coroutineLoop, variable)
--[[B8]]end) -- coroutine was resumed and reached the end. it is now dead.
--[[C4]] print(coroutine.status(coroutineLoop)) -- prints dead, because coroutine is dead
--[[C5]] wait(1)
------------~1 second passes
--[[C6]] print("SomethingRandom")
--[[C7]] wait(2)
------------~2 seconds pass
--[[C8]] return
--[[A5]]wait(2)
------------~2 seconds pass
--[[A6]]bindableFunctionVariable = bindableFunction:Invoke("randomVariable")
--[[C2]] print(coroutine.status(coroutineLoop)) -- prints dead
--[[C3]] coroutine.resume(coroutineLoop, variable) -- should error???????
--[[C4]] print(coroutine.status(coroutineLoop)) -- prints dead
--[[C5]] wait(1)
--[[C6]] print("SomethingRandom") -- you said this doesn't print, so the above resume really did error...
--[[C7]] wait(2)
--[[C8]] return
------------THE END
Fun coroutine experiment: run this in the command bar:
for _ in wait do end
If you understand why it prints TWO errors and why the second one doesn’t appear immediately, then you’re on your way to becoming a coroutine master.