Coroutine only firing once in for in pairs loop

I’m trying to make a script that will look through a folder and decide which lights will flicker by random chance, and it’s supposed to be able to apply to multiple by starting functions in different threads but whenever the first light is picked it stops the script. It works completely fine when I remove the coroutine. Spawn() gives me the same result.

Couritine enabled


**number randomizer set to 1,1 for the video

Couritine disabled


**set back to 1,4

local function lightFlicker(Light,Sound)
	local Volume = 0.8
	local specificLight = Light.Light1
	if math.random(1,2) == 1 then
		specificLight = Light.Light2
	end
	while true do
		wait(math.random(0.3,4))
		Sound.Volume = Volume
		Sound:Play()
		for i = 0,2 do
			specificLight.Color = Color3.new(0.705882, 0.705882, 0.541176)
			wait(0.05)
			specificLight.Color = Color3.new(0.992157, 0.917647, 0.552941)
			wait(0.05)
		end
		for i = 0,10 do
			Sound.Volume = Sound.Volume - 0.05
		end
		Sound:Stop()
	end
end

--part that wont work
local function randomizeLightFlicker()
	for lightNumber, Light in pairs(game.Workspace.Lights:GetChildren()) do
		if math.random(1,10) == 1 and Light.ClassName == "Model" then
                        --once one light starts flickering it ends the script
			print("Light #"..lightNumber.." is flickering")
			local Sound = Instance.new("Sound")
			Sound.SoundId = "rbxassetid://2058107176"
			Sound.Parent = Light
			local lightFlickerCoroutine = coroutine.wrap(lightFlicker(Light,Sound))
			lightFlickerCoroutine(Light,Sound)
		end
	end
end

randomizeLightFlicker()

so…

if math.random(1,10) == 1 and Light.ClassName == "Model" then

so given that there are 10 lights there would only be an average 50% chance to fire lights twice, this also explains why the light flickering happens to seemingly random lights in your examples.
try changing that line to

if Light.ClassName == "Model" then

then test it it should fire for all lights not just 1 or 2

I want there to be a random chance of each light flickering, the problem is that once one light gets the 1/10 chance then it completely stops the script. Even if there is a low chance I want there to occasionally be 2 or 3 flickering lights instead of just a maximum of one

well for one its unlikely thats its actually stops the script,
try

for lightNumber, Light in pairs(game.Workspace.Lights:GetChildren()) do
print("firing chance for "..Light.Number)
		if math.random(1,10) == 1 and Light.ClassName == "Model" then
                        --once one light starts flickering it ends the script
			print("Light #"..lightNumber.." is flickering")
			local Sound = Instance.new("Sound")
			Sound.SoundId = "rbxassetid://2058107176"
			Sound.Parent = Light
			local lightFlickerCoroutine = coroutine.wrap(lightFlicker(Light,Sound))
			lightFlickerCoroutine(Light,Sound)
		end
	end

you should find it’ll actually loop through all of them but only flicker some, and if you want like 2 or 3 then just make the 1/10 fraction larger to something like 2/10

what I mean when I say make the fraction larger

if math.random(2,10) == 1 and Light.ClassName == "Model" then

That’s why I gave the example of when the randomizer was set to 1,1, then every single time the if statement was true but it still didn’t fire anything after the first light. I might just be explaining it wrong but I’m just trying to make it to be able to flicker any number of lights instead of just a max of one.

edit i did that last part wrong it just made it impossible to fire, here’s the fix

local r = math.random(1,10)
if r == 1 or r == 2 and Light.ClassName == "Model" then

I did what you put and it still stops the script once it reaches a positive
image
image

hmm, well thats strange im going to relook at the script give me a bit

1 Like

ok so I’m just going to guess on this but try changing this line

local lightFlickerCoroutine = coroutine.wrap(lightFlicker(Light,Sound))

to

local lightFlickerCoroutine = coroutine.wrap(lightFlicker)

It works, but to make it work I had to remove everything in the corouitine that had to do with the variables. I’ll see if I can make something work. Thanks for your help.

the reason i mentioned the that line was that was the line that warps the coroutine, the line right after calls it, that line is where the variables go its like a calling a function

Perhaps try

coroutine.wrap(lightFlicker)(Light,Sound)

To actually call the function

2 Likes

That works perfectly, thanks. I’m still learning so could you explain why that works?

coroutine.wrap(function()

end)

Over there I just created a thread, but didn’t actually call it. That’s the catch on coroutine.wrap. Nothing much on it except that in this case your function was premade so you didn’t have to create a new one so we just.

coroutine.wrap(function)(args)

The paretheses at the end is like the paretheses we use when calling the function. Of course alternatively you could do.

coroutine.wrap(function()
    lightFlicker(Light,Sound)
end)()

But like, just making a new function here so idké if it’s good practice.

And there’s also coroutine.create. Been a while I didn’t use it but I think it’s like this

coroutine.resume(coroutine.create(function()
    lightFlicker(Light,Sound)
end)) -- if causing confusion: 2 paretheses to close off the create( and resume(

-- or do

local thing = coroutine.create(function()
    lightFlicker(Light,Sound)
end)
coroutine.resume(thing)
2 Likes

Thanks again for helping me out

1 Like