Unfortunately, coroutines are currently broken
To get around this, I made a lua module that basically emulates coroutines using BindableEvents
It has an identical API to lua coroutines so it is very easy to swap in by adding to the top of your script local coroutine=require(path.to.coroutine)
The only downsides are that it:
- can’t get function return values if thread isn’t made with the module
- can’t resume threads that aren’t yielded with the module (e.g: wait,BindableEvents,actual coroutines,etc)
The first one is rarely used though (and when you do need it simply just wrap the Roblox thread in a coroutine made by this module) and the second is only used if you have some ultra hacky code(? if you have use cases for it I’m very curious to see ;P) so these two restrictions are more or less negligible
Here is a Roblox model of the code
If you find any bugs/have suggestions please message me on discord Acreol#0001
Thanks
--[[
Fix to https://devforum.roblox.com/t/modulescripts-that-yield-with-coroutine-yield-will-break-parent-thread/239567
Can't get function return Values if thread isn't made with this module
Can't resume threads that aren't yielded with this module (e.g: wait,BindableEvents,actual coroutines,etc)
--]]
local md={}
local data=setmetatable({},{
__mode='k',
__index=function(data,t)
data[t]={
ev=Instance.new('BindableEvent'),
args={},--passed through resume
ret={},--returned from function/yield
}
return data[t]
end,
})
local function pack(...)
return{n=select('#',...),...,}
end
md.running=coroutine.running
md.status=coroutine.status
md.yield=function(...)
local data=data[md.running()]
data.ret=pack(...)
data.ev.event:Wait()
return unpack(data.args,1,data.args.n)
end
md.resume=function(t,...)
local data=data[t]
data.args=pack(...)
data.ret={}
local ok,msg=pcall(data.ev.fire,data.ev)
data.args={}
local ret=data.ret
data.ret={}
if ok then
return ok,unpack(ret,1,ret.n)
else
return ok,msg
end
end
md.create=function(f)
local t
coroutine.wrap(function()
t=md.running()
data[t].ret=pack(f(md.yield()))
end)()
return t
end
md.wrap=function(f)
return coroutine.wrap(function(...)
data[md.running()].ret=pack(f(...))
end)
end
return md