How to 'skip' yield on module script

So I currently have 2 scripts;

1 module that has a while loop inside and a normal script that fires the module

The issue:
If I want to fire that same module twice, basically firing to while loops at the same time, it yields until the first while loop is done. Basically, I want to fire it and not yield. Kind of like a coroutine.

Module script:

local moduleScript = {}

function moduleScript.loopFunction(number)

	while true do --yes I know, an infite loop
		print(number)
		wait(1)
	end

end
return moduleScript  

Normal script:

module = require(game.Workspace.ModuleScript)

module.loopFunction(1)
module.loopFunction(2) --this will not print, as it yields for the function above to finish

Current output:
1 (continous)

Output wanted:
1 (continous)
2 (continous)

Thanks, and have a nice day!

2 Likes

Use a separate thread such as

spawn(function() 
-- Do stuff
end)

or break out of the first loop.

For example:

local moduleScript = {}

function moduleScript.loopFunction(number)
spawn(function()
	while true do
		print(number)
		wait(1)
	end
end)
end
return moduleScript  
2 Likes

Inside the module like;

local moduleScript = {}

spawn(function moduleScript.loopFunction(number))

	while true do --yes I know, an infite loop
		print(number)
		wait(1)
	end

end
return moduleScript

Edit; you posted the script at the exact same time. You beat me to it!

Edit 2: Turns out mine is different-

Thats not how spawn works. So I would rather just incase the loop instead of the function

You can also use coroutine

1 Like

I will try that out, thanks. I will come back shortly after testing. Thanks

Use coroutines

coroutine.wrap(s.loopFunction)(2)
coroutine.wrap(s.loopFunction)(2)

As others have suggested, you need to choose an asynchronous solution to your problem. While spawn is simple and works fine when used sparingly, you should avoid it in favor of coroutines. What @hell_ish suggested (coroutine.wrap) will likely be the simplest solution to your problem and is generally better than spawn, but depending on what you’re doing in these loops there may be a better solution.

RunService.Stepped could potentially be better if these are tight loops (running very often) or if they need precise timing. If these are updating a visual indicator you’d want RunService:BindToRenderStep. If this is just regular game coordination (like waiting 30 seconds between rounds, etc) then doing what you’re doing is fine.

1 Like

Thanks for your answer @heII_ish and @Ozzypig

Why is using coroutines better than spawn, just wondering out of curiousity.

Spawn has a wait() before your function is actually ran.

If you wanna use spawn just because I guess it’s easier or more readable, you can just replace the spawn function with this.

local function spawn(func, ...)
     return coroutine.wrap(func)(...)
end

If you need it to run only after your code that summoned it is really, you can use a Heartbeat:Wait() which is short and shouldn’t care any issues.

You probably wouldn’t understand how coroutines work, so this is useless to you.

local RunService = game:GetService('RunService')

local function spawn(func, ...)
    return coroutine.wrap(function()
        RunService.Heartbeat:Wait();
        func(...)
    end)()
end

Overall just avoid spawn and you should be fine performance wise.

Why would you ever need a module script that yields forever?

If you can tell me the logistics of using a forever yielding loop, I can try to provide an alternative and resource friendly way of doing it.

@LucasTutoriaisSaimo @Ozzypig @heII_ish
Thanks for your answers, and my apologies for such a delayed reply!
After @Ozzypig’s recommendation, I have chosen to use coroutines instead of spawn(). But how would I use it in my script, I tried calling the function/module like this:

coroutine.wrap(module.loopFunction(1))
coroutine.wrap(module.loopFunction(2))

That didn’t work, it just behaved the same as the original script.

Do I need to wrap the function inside of the module into a coroutine? Thanks for any help :smiley:

Edit:
I tried this, but I got this error: attempt to call a thread value.

Module:

local moduleScript = {}

moduleScript.functionTest = coroutine.create(function(number)
	while true do 
		print(number)
		wait(1)
	end
end)


return moduleScript  

Script where calling:

module = require(game.Workspace.ModuleScript)

coroutine.resume(module.functionTest(1)) --error message: attempt to call a thread value.
module.functionTest(2)

(I tried both coroutine.wrap() and coroutine.continue() )

You have to wrap the function before calling it

coroutine.wrap(module.loopFunction)(1)
coroutine.wrap(module.loopFunction)(2)
2 Likes