[Solved] Issue with CollectionService

Ciao :wave:

Making a game right now, and I’m currently working on the Street Light system.

The thing is:

The script works fine for ONE light, however as soon as I add a second street light, only one of them works. The other one doesn’t change materials, aka does NOTHING.

Only one: :white_check_mark:

Additional light: :x:
test3

As soon as there’s another light, one of them stops working. It doesn’t matter how many are added, only one will work.

Here’s the script:

local CollectionService = game:GetService("CollectionService")

local lightpart = game.CollectionService:GetTagged("Bulb")

for _, lightpart in pairs (lightpart) do
 while true do
	 task.wait(0.1)
	 if game.Lighting:GetMinutesAfterMidnight() > 6 * 60 then
		lightpart.Material = Enum.Material.Plastic
	 end
	 if game.Lighting:GetMinutesAfterMidnight() > 18 * 60 then
		lightpart.Material = Enum.Material.Neon	
	 end
   end
end

Keep in mind that I didn’t script the Light itself turning on and off (the Surfacelight inside of my light bulb in the streetlight model)

Thanks for ANY help! :grin:

1 Like

It will only run one light part because it stays in this while loop forever. Contain the while loop in task.spawn() to fix this. This is not an issue with CollectionService.

3 Likes

This function runs a task seperatly, so your other code doesn’t wait for it to finish.

print(1)
task.spawn(function()
    task.wait(1)
    print(3)
end)
print(2)

-- Output:
-- 1
-- 2
-- 3
2 Likes

The issue with your script is that the while loop is causing the script to get stuck and not progress through the loop to the next street light. The script is continuously running the loop for the first street light, preventing it from running the loop for the second street light.

To fix this issue, you can use a coroutine to run the loop for each street light separately. Here’s an example code that demonstrates how to use a coroutine to change the material of each street light separately:

> local CollectionService = game:GetService("CollectionService")
> local lightparts = CollectionService:GetTagged("Bulb")
> 
> for _, lightpart in pairs(lightparts) do
>     coroutine.wrap(function()
>         while true do
>             if game.Lighting:GetMinutesAfterMidnight() > 6 * 60 then
>                 lightpart.Material = Enum.Material.Plastic
>             end
>             if game.Lighting:GetMinutesAfterMidnight() > 18 * 60 then
>                 lightpart.Material = Enum.Material.Neon
>             end
>             task.wait(0.1)
>         end
>     end)()
> end
1 Like

While blueberry solution will work, Your script is will be very inefficient, especially when You will add lots of lighting. Not only You are polling lighting service ten times per second, but You will also do it (if you go with this solution) for every light there is.

The best solution will be to switch lights in Your day/night control script, as this script will know exactly what time is it.

The next best thing will be to connect to lighting changed signal:

local CollectionService = game:GetService("CollectionService")

local lightpart = game.CollectionService:GetTagged("Bulb")

local lightsOn = false -- variable to remember the state of the lights
game.Lighting.LightingChanged:Connect(function()

   if game.Lighting:GetMinutesAfterMidnight() > 6 * 60 and lightsOn then
      lightsOn = false
      for _, lightpart in pairs (lightpart) do
         lightpart.Material = Enum.Material.Plastic
      end
   elseif game.Lighting:GetMinutesAfterMidnight() > 18 * 60 and not lightsOn then
     lightsOn = true
      for _, lightpart in pairs (lightpart) do
         lightpart.Material = Enum.Material.Neon	
      end
   end

end)
1 Like

DAMN! I didn’t even know “coroutine” was a thing.

It works now, thanks for teaching me what coroutine is basically!

:checkered_flag:

1 Like

Interesting! I didn’t even know task.spawn was a thing either… Shows that I’m still a novice…

Do you mean blueberries’s or Snack_tack’s?

task.spawn() is essentially the same as coroutine.wrap(). Snack_Tack elaborated on blueberry, but their solution, while valid, results in creation of x amount of couroutines that will consume significant part of server resources (x is amount of lights).

They however answered Your original question, while I provided an alternative solution.

1 Like

Oh okay, thanks for clarifying.

I tried the script you added, and it doesn’t seem to work. Or did I just read it wrong, and am I supposed to add something to it myself?

Thanks!

That will depend on how do you control time in Your game. As long as time is controlled by the server script, this event will fire.

It WON’T work if you change time manually in studio.

1 Like

Okay, it works now… Kinda…

The light stays on during the day, and blinks during the night:
https://gyazo.com/32cb5786d15817d0bd428f3614591250

And yeah, it stays on during the day :grimacing: My day night script is serverscript service by the way

Thanks!

It seems the conditions for turning on and off the lights are wrong, somehow I have not noticed that before.
The first condition checks if it is past 6 AM. If it is it turns off the lights.
The second condition checks if it is past 6 PM. If it is it turns on the lights.

Problem is, past 6 PM and before midnight both conditions are true so the lights flicker. After midnight and before 6AM nothing happens, so it will depend on the what state the lights were left just before 12 AM.

Proper conditions will be:

if game.Lighting:GetMinutesAfterMidnight() > 6 * 60 
   and game.Lighting:GetMinutesAfterMidnight() < 18 * 60 
   and lightsOn then

and:

--EDITED!
if (game.Lighting:GetMinutesAfterMidnight() < 6 * 60 
   or game.Lighting:GetMinutesAfterMidnight() > 18 * 60)
   and not lightsOn then

EDIT: Corrected second condition to use or.

1 Like
local CollectionService = game:GetService("CollectionService")

local lightpart = game.CollectionService:GetTagged("Bulb")

local lightsOn = false -- variable to remember the state of the lights
game.Lighting.LightingChanged:Connect(function()

	if game.Lighting:GetMinutesAfterMidnight() > 6 * 60 
		and game.Lighting:GetMinutesAfterMidnight() < 18 * 60 
		and lightsOn then
        local CollectionService = game:GetService("CollectionService")

local lightpart = game.CollectionService:GetTagged("Bulb")

local lightsOn = false -- variable to remember the state of the lights
game.Lighting.LightingChanged:Connect(function()

	if game.Lighting:GetMinutesAfterMidnight() > 6 * 60 
		and game.Lighting:GetMinutesAfterMidnight() < 18 * 60 
		and lightsOn then
		lightsOn = false
		for _, lightpart in pairs (lightpart) do
			lightpart.Material = Enum.Material.Neon
		end
		elseif (game.Lighting:GetMinutesAfterMidnight() < 6 * 60 
			or game.Lighting:GetMinutesAfterMidnight() > 18 * 60)
			and not lightsOn then
		for _, lightpart in pairs (lightpart) do
			lightpart.Material = Enum.Material.Glass	
		end
	end

end)
		for _, lightpart in pairs (lightpart) do
			lightpart.Material = Enum.Material.Neon
		end
		elseif (game.Lighting:GetMinutesAfterMidnight() < 6 * 60 
			or game.Lighting:GetMinutesAfterMidnight() > 18 * 60)
			and not lightsOn then
		for _, lightpart in pairs (lightpart) do
			lightpart.Material = Enum.Material.Glass	
		end
	end

end)

Like this?

You forgot to update the lightsOn variable in the second condition. Plus conditions are swapped, first should TURN OFF the lights. Also there is an extra pasted code maybe? Anyways it should be like this:

game.Lighting.LightingChanged:Connect(function()

	if game.Lighting:GetMinutesAfterMidnight() > 6 * 60 
		and game.Lighting:GetMinutesAfterMidnight() < 18 * 60 
		and lightsOn then
		lightsOn = false
		for _, lightpart in pairs (lightpart) do
			lightpart.Material = Enum.Material.Glass --glass here
		end
	elseif (game.Lighting:GetMinutesAfterMidnight() < 6 * 60 
			or game.Lighting:GetMinutesAfterMidnight() > 18 * 60)
			and not lightsOn then
		lightsOn = true --missed this
		for _, lightpart in pairs (lightpart) do
			lightpart.Material = Enum.Material.Neon --neon here
		end
	end

end)
1 Like

Yes! It works!

Thanks for explaining everything carefully, by the way :smile:

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.