There are a few things in your script that could be improved.
The first thing I would remove is the while true
loop and replace it with heartbeat from RunService.
From reading your original code I get the impression that you have put that script inside each individual light, the code below does not need to be placed under each object, instead it needs 1 copy inside ServerScriptService
. This is good practice for multiple reasons; to start this method is a lot more performant especially if you have lots of lights. The next reason is improved maintainability, should you want to modify the code, you only have to change the 1 script not all of them. This also extends to if you start wanting to use Rojo or something similar, those tools really are not designed to have code scattered around the workspace randomly.
To remove the requirement for it to be placed under every object, I am using CollectionService to find all of the lights then looping though that list to modify them individually. I would recommend using the TagEditor plugin to make tagging the lights to a collection much easier. To make each light ‘unique’ each individual light stores data inside itself using attributes, the code below requires 2 boolean attributes called addRange
and addBrightness
I would recommend randomising there starting state to make the lights less in sync. Should you wish for even more randomness you could add the speed variable as an attribute and modify the code accordingly.
The first if statement if tick() >= lastUpdate + speed then
is used to only run the following code every speed
seconds.
To avoid the necessity for the messy nested if statements in the original code to clamp the values I have replaced them with math.min/max
.
The next thing that I would change simply for aesthetics is having random colours picked, this is because you are very likely to end up with ugly colours choses (brown, grey etc.) which will not look good for lights. In the code below I have created a table with a selection of different light colours that can be chosen.
To make the transitions of the variables smooth I have also incorporated TweenService, feel free to play around with tInfo
to make it transition however you would like it to.
local runService = game:GetService("RunService")
local collectionService = game:GetService("CollectionService")
local tweenService = game:GetService("TweenService")
local allPointLights = collectionService:GetTagged("DiscoLights") -- Negates the need to have this script in every light and makes adding lights easier (Get tag editor plugin)
local lightColours = { -- Ensures lights only have 'good' colours, e.g. no brown / grey lights
Color3.fromRGB(255, 0, 0),
Color3.fromRGB(0, 255, 0),
Color3.fromRGB(0, 110, 255),
Color3.fromRGB(187, 19, 230),
Color3.fromRGB(241, 184, 26),
}
local speed, lastUpdate = 1, tick()
runService.Heartbeat:Connect(function(dt) -- Replaces the while true loop
if tick() >= lastUpdate + speed then -- Only updates every second (set by variable above)
for i = 1, #allPointLights do
-- Colour
local targetColour = lightColours[math.random(1, #lightColours)]
-- Brightness
local addBrightness = allPointLights[i]:GetAttribute("addBrightness") -- Bool attribute
local randomBright = math.random()*4
local targetBright
if addBrightness then
targetBright = math.max(40, allPointLights[i].Brightness + randomBright)
else
targetBright = math.min(15, allPointLights[i].Brightness - randomBright)
end
allPointLights[i]:SetAttribute("addBrightness", not addBrightness) -- Inverts bool
-- Range
local addRange = allPointLights[i]:GetAttribute("addRange") -- Bool attribute
local randomRange = math.random()*3
local targetRange
if addBrightness then
targetRange = math.max(40, allPointLights[i].Range + randomRange)
else
targetRange = math.min(15, allPointLights[i].Range - randomRange)
end
allPointLights[i]:SetAttribute("addRange", not addBrightness)
-- Tween changes to make it look nice (Could also lerp)
local tInfo = TweenInfo.new(speed, Enum.EasingStyle.Cubic)
local goal = {
Color = targetColour,
Brightness = targetBright,
Range = targetRange
}
tweenService:Create(allPointLights[i], tInfo, goal):Play()
end
end
end)