I am trying to implement a system where, once an int value changes, I need 600+ lights in my game to change their color at once. I’m not sure of an efficient way to do this. I’ve tried working with the below script, but I think it is creating an immense amount of lag in general in the game. Is there a better way to do this?
for _,brick in pairs(workspace.AmbienceLights:GetChildren()) do
wait()
game:GetService("ReplicatedStorage").GameValues.IntensityLevel.Changed:Connect(function()
if game:GetService("ReplicatedStorage").GameValues.IntensityLevel.Value == 1 then
brick.BrickColor = brick.OriginalColor.Value
if brick:FindFirstChild("PointLight") then
brick.PointLight.Color = BrickColor.White().Color
end
else
brick.BrickColor = BrickColor.Red()
if brick:FindFirstChild("PointLight") then
brick.PointLight.Color = BrickColor.Red().Color
end
end
end)
end
You’re making 600 different connections, yes, that’s going to be expensive. Just connect to the IntensityLevel’s Changed event once, and then loop through and change all the bricks properties. (Don’t use wait() in that loop or it’ll have a noticeable delay.)
Try checking if the remainder of the index (which you’re discarding right now) divided by some number (say, 50) is 0, so that it only waits every 50 iterations or so. There will still be a noticeable delay, but it shouldn’t be as bad.
Switch the loop and the event listener around.
That way you will only have one event listener and it just iterates through all the parts.
local intensityLevel = game:GetService("ReplicatedStorage").GameValues.IntensityLevel
intensityLevel.Changed:Connect(function()
for _, brick in ipairs(workspace.AmbientLights:GetChildren()) do
if (intensityLevel.Value == 1) then
brick.BrickColor = brick.OriginalColor.Value
if (brick:FindFirstChild("PointLight")) then
brick.PointLight.Color = BrickColor.White().Color
end
else
brick.BrickColor = BrickColor.Red()
if (brick:FindFirstChild("PointLight")) then
brick.PointLight.Color = BrickColor.Red().Color
end
end
end
end)
(this might be overly micro-optimising, apologies)
Adding on to your suggestion, if the number of ambient lights does not change, consider putting all the lights into a table. You’ll only have to run GetChildren() and FindFirstChild() once when the game starts, and reference the table whenever needed. I would also localise some values to reduce the amount of work done in the for loop.
local intensityLevel = game:GetService("ReplicatedStorage").GameValues.IntensityLevel
local AmbientLights = {}
local Red = BrickColor.Red()
local White = BrickColor.White()
local RedColor3 = Red.Color
local WhiteColor3 = White.Color
for _, brick in pairs(workspace.AmbientLights:GetChildren()) do
local brickData = {}
brickData["Part"] = brick
brickData["OriginalColor"] = brick.OriginalColor.Value
local PointLight = brick:FindFirstChild("PointLight")
if PointLight then
brickData["PointLight"] = PointLight
end
table.insert(AmbientLights, brickData)
end
intensityLevel.Changed:Connect(function()
for _, brickData in ipairs(AmbientLights) do
local brick = brickData["Part"]
local OriginalColor = brickData["OriginalColor"]
local PointLight = brickData["PointLight"]
if (intensityLevel.Value == 1) then
brick.BrickColor = OriginalColor
if PointLight then
PointLight.Color = WhiteColor3
end
else
brick.BrickColor = Red
if PointLight then
PointLight.Color = RedColor3
end
end
end
end)