Very Long Lighting Code, May Need Shortening

  • What does the code do and what are you not satisfied with?
    The code operates how a light works. Changes intensity and color using randomization.
    • What potential improvements have you considered?
      I am not sure, I just started coding a week or two ago in Lua.
    • How (specifically) do you want to improve the code?
      Perhaps make the code shorter, is there something that can be done to optimize the code? The code looks ridiculously long for all that it’s doing and I am not sure if that’s normal because I am new. This code is being run on 8 lights in my disco module and I am concerned that if I added more it could slow the game down.
local pointLight = script.parent
pointLight.Brightness = 0
pointLight.Range = 0
pointLight.Color = Color3.fromRGB(0,0,0)
local x = 0
local y = 0
local z = 0
local redColorAdd = 0
local greenColorAdd = 0
local blueColorAdd = 0
local redColor = 0
local greenColor = 0
local blueColor = 0
local range = 0
local brightness = 0
local addbrightness = true
local addrange = true
local addRed = true
local addGreen = true
local addBlue = true
while true do
	wait(0.1)
	local random = Random.new()
	if redColor < 127 then
		x = (redColor+1)^(0.25)
	end
	if redColor > 127 then
		x = (256-redColor)^(0.25)
	end
	if greenColor < 127 then
		y = (greenColor+1)^(0.25)
	end
	if greenColor > 127 then
		y = (256-greenColor)^(0.25)
	end
	if blueColor < 127 then
		z = (blueColor+1)^(0.25)
	end
	if blueColor > 127 then
		z = (256-blueColor)^(0.25)
	end
	local redColorAdd = math.floor(random:NextNumber(x*0.15,x*7))
	local greenColorAdd = math.floor(random:NextNumber(y*0.15,y*7))
	local blueColorAdd = math.floor(random:NextNumber(z*0.15,z*7))
	if addRed == true then 
		redColor = redColorAdd + redColor
		if redColor > 255 then
			redColor = 255-(redColor-255)
			addRed = false
		end
	end
	if addGreen == true then 
		greenColor = greenColorAdd + greenColor
		if greenColor > 255 then
			greenColor = 255-(greenColor-255)
			addGreen = false
		end
	end
	if addBlue == true then 
		blueColor = blueColorAdd + blueColor
		if blueColor > 255 then
			blueColor = 255-(blueColor-255)
			addBlue = false
		end
	end
	if addRed == false then 
		redColor = redColor - redColorAdd
		if redColor < 0 then
			redColor = -redColor	
			addRed = true
		end
	end
	if addGreen == false then 
		greenColor = greenColor - greenColorAdd
		if greenColor < 0 then
			greenColor = -greenColor
			addGreen = true
		end
	end
	if addBlue == false then 
		blueColor = blueColor - blueColorAdd
		if blueColor < 0 then
			blueColor = -blueColor
			addBlue = true
		end
	end
	local randomizer1 = math.random()*4
	local randomizer2 = math.random()*3
	if addbrightness == true then 
		brightness = brightness + randomizer1
		if brightness > 40 then
			brightness = 40-(brightness-40)
			addbrightness = false
		end
	end
	if addbrightness == false then 
		brightness = brightness - randomizer1
		if brightness < 5 then
			brightness = 10-(brightness-10)	
			addbrightness = true
		end
	end
	if addrange == true then 
		range = range + randomizer2
		if range > 60 then
			range = 60-(range-60)
			addrange = false
		end
	end
	if addrange == false then 
		range = range - randomizer2
		if range < 15 then
			range = 15-(range-15)	
			addrange = true
		end
	end
	pointLight.Color = Color3.fromRGB(redColor,greenColor,blueColor)
	pointLight.Brightness = brightness
	pointLight.Range = range
end

Note: What to do if value is 127,127,127

local pointLight = script.parent
pointLight.Brightness = 0
pointLight.Range = 0
pointLight.Color = Color3.fromRGB(0,0,0)
local x = 0
local y = 0
local z = 0
local redColorAdd = 0
local greenColorAdd = 0
local blueColorAdd = 0
local redColor = 0
local greenColor = 0
local blueColor = 0
local range = 0
local brightness = 0
local addbrightness = true
local addrange = true
local addRed = true
local addGreen = true
local addBlue = true
while wait(0.1) do
	local random = Random.new()
	if redColor < 127 then
		x = (redColor+1)^(0.25)
	elseif redColor > 127 then
		x = (256-redColor)^(0.25)
	end
	if greenColor < 127 then
		y = (greenColor+1)^(0.25)
	elseif greenColor > 127 then
		y = (256-greenColor)^(0.25)
	end
	if blueColor < 127 then
		z = (blueColor+1)^(0.25)
	elseif blueColor > 127 then
		z = (256-blueColor)^(0.25)
	end
	local redColorAdd = math.floor(random:NextNumber(x*0.15,x*7))
	local greenColorAdd = math.floor(random:NextNumber(y*0.15,y*7))
	local blueColorAdd = math.floor(random:NextNumber(z*0.15,z*7))
	if addRed then 
		redColor = redColorAdd + redColor
		if redColor > 255 then
			redColor = 255-(redColor-255)
			addRed = false
		end
	else
		redColor = redColor - redColorAdd
		if redColor < 0 then
			redColor = -redColor	
			addRed = true
		end
	end
	if addGreen then 
		greenColor = greenColorAdd + greenColor
		if greenColor > 255 then
			greenColor = 255-(greenColor-255)
			addGreen = false
		end
	else
		greenColor = greenColor - greenColorAdd
		if greenColor < 0 then
			greenColor = -greenColor
			addGreen = true
		end
	end
	if addBlue then 
		blueColor = blueColorAdd + blueColor
		if blueColor > 255 then
			blueColor = 255-(blueColor-255)
			addBlue = false
		end
	else
		blueColor = blueColor - blueColorAdd
		if blueColor < 0 then
			blueColor = -blueColor
			addBlue = true
		end
	end
	local randomizer1 = math.random()*4
	local randomizer2 = math.random()*3
	if addbrightness then 
		brightness = brightness + randomizer1
		if brightness > 40 then
			brightness = 40-(brightness-40)
			addbrightness = false
		end
	else
		brightness = brightness - randomizer1
		if brightness < 5 then
			brightness = 10-(brightness-10)	
			addbrightness = true
		end
	end
	if addrange then 
		range = range + randomizer2
		if range > 60 then
			range = 60-(range-60)
			addrange = false
		end
	else
		range = range - randomizer2
		if range < 15 then
			range = 15-(range-15)	
			addrange = true
		end
	end
	pointLight.Color = Color3.fromRGB(redColor,greenColor,blueColor)
	pointLight.Brightness = brightness
	pointLight.Range = range
end
2 Likes

Good catch, I’ll make it a greater or equal to instead of just greater than. Thank you!

Edit: whoops, just noticed the code you attached with the reply. Will update my script.

1 Like

One tip is that you can define all of your variables on one line. For example,

local varname1, varname2 = varvalue1, varvalue2

This chunk:

local x = 0
local y = 0
local z = 0
local redColorAdd = 0
local greenColorAdd = 0
local blueColorAdd = 0
local redColor = 0
local greenColor = 0
local blueColor = 0
local range = 0
local brightness = 0
local addbrightness = true
local addrange = true
local addRed = true
local addGreen = true
local addBlue = true

Can be changed into this chunk:

local x, y, z, redColorAdd, greenColorAdd, blueColorAdd, redColor, greenColor, blueColor, range, brightness, addbrightness, addrange, addRed, addGreen, addBlue = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, true, true, true, true, true
2 Likes

It can get messy if the line becomes too long. Better for organizing.

2 Likes

I didn’t know that, thanks! I will do that for the different color variables in groups of three and also for
x, y, z.

1 Like

You should use else if instead of creating a new statement each time.

2 Likes

I noticed that but he has a lot of embedded if statements so that may not work too well.

1 Like

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)
3 Likes

Wow. I greatly appreciate this answer, and also the extra explanation behind each function! There is clearly a lot I have to learn about coding in Lua.