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)