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.
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)
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.
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
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)
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.
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
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)
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)