How to make a light that flickers while on but does nothing while is off

  1. What do I want to achieve? I want to have this light I made flicker while it’s on according to a sound I have (I know this works so far), but when the light is off it doesn’t change (it just stays off with no properties changed).

  2. What is the issue? I think I have multiple issues. I’m running an if statement inside a RunService.Heartbeat function. I did this because I want the light to be constantly updated, but the start (on) or stop (off) functions to run once and have the RunService function just wait until the lightStatus value has changed. The lightStatus value changes based on the light’s switch being flicked on or off, on being true while off being false.

  3. What solutions have I tried so far? I tried searching up some solutions but couldn’t really find anything to help me. I always get stuck in a loop inside a loop waiting on each other combo a lot and always get stuck so I thought this would also be a good time to learn how to stop doing that.

This script below in in a local script called “FlickeringLightScript” inside StarterPlayerScripts.

If I need to state any more details I would be more than happy to.

My Code:

local RunService = game:GetService("RunService")

local Light = workspace.Office.Light.Bulb.SpotLight
local Sound = workspace.Office.Light.FlickeringLightSound

local originalAngle = Light.Angle
local originalTransparency = Light.Parent.Transparency

local lightSwitch = workspace.Office:WaitForChild("Lightswitch")
local Switch = lightSwitch:WaitForChild("Switch")
local Main = lightSwitch:WaitForChild("Main")
local lightPrompt = Main:WaitForChild("LightSwitchPrompt")
local lightSound = Main:WaitForChild("LightSwitchSound")

local lightStatus = true

local function start()
	Sound.Looped = true
	Sound:Play()
	Light.Parent.Material = Enum.Material.Neon
	Light.Enabled = true
	repeat 
		local currentLoudness = Sound.PlaybackLoudness
		Light.Angle = Light.Angle - currentLoudness * 5
		Light.Parent.Transparency = Light.Parent.Transparency + currentLoudness / 10
		wait(0.05)
		Light.Angle = originalAngle
		Light.Parent.Transparency = originalTransparency
	until lightStatus == false
end

local function stop()
	Sound.Looped = false
	Sound:Stop()
	Light.Parent.Material = Enum.Material.SmoothPlastic
	Light.Parent.Transparency = 0
	Light.Enabled = false
end

RunService.Heartbeat:Connect(function()
	if lightStatus == true then
		start()
		-- I do not know what to do here.
	else
		stop()
		-- I do not know what to do here.
	end
end)

lightPrompt.Triggered:Connect(function()
	lightSound:Play()
	if lightStatus == true then
		lightStatus = false
		Switch.Orientation = Vector3.new(55, 180, 180)
		lightPrompt.ActionText = "Turn Lights On"
	else
		lightStatus = true
		Switch.Orientation = Vector3.new(35, 0, 0)
		lightPrompt.ActionText = "Turn Lights Off"
	end
end)

Thank you for your help or even your time reading this!

1 Like

So, you want the light to flicker while its on, and you want the heartbeat to stop while its off?

When the player clicks the switch to turn it on, connect the heartbeat and store it into a variable, when the player clicks to turn it off, disconnect the variable (disconnecting the heartbeat) so the heartbeat stops.

Use the heartbeat steps to change the properties of the flickering

I’m sorry, I don’t think I am following. I have a rough understanding of what you are saying, but I am having trouble incorporating your solution into my script.

Are you saying something along the lines of:

local example

...

example = RunService.Heartbeat:Connect()

Ok, I read your script, and seems like you want the light to fluctuate based on the PlaybackLoudness of the sound, sorry I didnt notice that.

Well, its almost the same process, you’ll be using the heartbeat to read the loudness of the sound, and change the light properties depending on that right?

So, when player turns on the light, you connect the heartbeat, letting it changing the properties of the light by reading the loudness of the sound, when player turns off the light, you disconnect the heartbeat.

Something like this, just need to reference and adjust the properties of the light and sound in the heartbeat, Im gonna make a test too

local RS = game:GetService("RunService")

local HeartBeatConn

local switch = false

game.Workspace.Part.ProximityPrompt.Triggered:Connect(function()
	if not switch then
		switch = true
		HeartBeatConn = RS.Heartbeat:Connect(function()
			print("flickering")
			-- Need to reference the light and sound properties
			Light.Angle = Light.Angle - currentLoudness * 5
			Light.Parent.Transparency = Light.Parent.Transparency + currentLoudness / 10
		end)
	else
		switch = false
		HeartBeatConn:Disconnect() -- stop the heartbeat updating
	end
end)

Here’s a post I found just by searching the forums for “currentLoudness”:

Thank you for that suggestion, although I made that post lol. That is not quite the same issue I am having currently, but thank you again for the help.

Isn’t it?
As stated, just use one function to turn the light off, and stop the Heartbeat loop.
Use the other function to do the exact same as you were doing the first time.

Im using this, and the light flickers based on the PLaybackloudness of the sound, updated by the heartbeat, kinda going on rhythm, but idk if thats what you looking for:

local RS = game:GetService("RunService")

local HeartBeatConn

local switch = false

local Light = game.Workspace:WaitForChild("Light"):WaitForChild("SurfaceLight")

local Sound = game.Workspace:WaitForChild("Sound"):WaitForChild("Sound")


game.Workspace.Part.ProximityPrompt.Triggered:Connect(function()
	if not switch then
		switch = true
		Sound:Play()
		HeartBeatConn = RS.Heartbeat:Connect(function()
			print("flickering")
			Light.Angle = 0.18 * Sound.PlaybackLoudness
		end)
	else
		switch = false
		Sound:Stop()
		HeartBeatConn:Disconnect()
	end
end)

I tried something like this:

local RunService = game:GetService("RunService")

local Light = workspace.Office.Light.Bulb.SpotLight
local Sound = workspace.Office.Light.FlickeringLightSound

local originalAngle = Light.Angle
local originalTransparency = Light.Parent.Transparency

local lightSwitch = workspace.Office:WaitForChild("Lightswitch")
local Switch = lightSwitch:WaitForChild("Switch")
local Main = lightSwitch:WaitForChild("Main")
local lightPrompt = Main:WaitForChild("LightSwitchPrompt")
local lightSound = Main:WaitForChild("LightSwitchSound")

local HeartBeatConn

local switch = true

lightPrompt.Triggered:Connect(function()
	lightSound:Play()
	if switch == true then
		switch = false
		Sound.Looped = true
		Sound:Play()
		Light.Parent.Material = Enum.Material.Neon
		Light.Enabled = true
		Switch.Orientation = Vector3.new(55, 180, 180)
		lightPrompt.ActionText = "Turn Lights On"
		HeartBeatConn = RunService.Heartbeat:Connect(function()
			print("flickering")
			-- Need to reference the light and sound properties
			local currentLoudness = Sound.PlaybackLoudness
			Light.Angle = Light.Angle - currentLoudness * 5
			Light.Parent.Transparency = Light.Parent.Transparency + currentLoudness / 10
			wait(0.05)
			Light.Angle = originalAngle
			Light.Parent.Transparency = originalTransparency
		end)
	else
		switch = true
		Switch.Orientation = Vector3.new(55, 180, 180)
		lightPrompt.ActionText = "Turn Lights On"
		HeartBeatConn:Disconnect() -- stop the heartbeat updating
	end
end)

Issue with that is that the light doesn’t flicker at first. The light is on by default, sorry I didn’t already mention that.

I’m not quite sure that will fix my issue, did you see my reply right above this one?

Explain more about whats your goal. I understand you want the light to flicker at the rhythm of music by changing the Light.Angle based on the Playbackloudness

So with this script here I believe we are getting closer to what I would like. The light and switch are both on by default (right when you join the game they are on), this is a one player game so no need to worry about how this looks on the server side or anything. Anyway, this script below will work if the lights were off by default, but they aren’t. I need the script to run the flicker function I guess until the player turns the light off, once they do, then this if statement would work instead. Does that makes sense? Loop first, then once the lights go out it waits for the Proximity prompt and does the if statement inside of that function.

Here’s the script:

local RunService = game:GetService("RunService")

local Light = workspace.Office.Light.Bulb.SpotLight
local Sound = workspace.Office.Light.FlickeringLightSound

local originalAngle = Light.Angle
local originalTransparency = Light.Parent.Transparency

local lightSwitch = workspace.Office:WaitForChild("Lightswitch")
local Switch = lightSwitch:WaitForChild("Switch")
local Main = lightSwitch:WaitForChild("Main")
local lightPrompt = Main:WaitForChild("LightSwitchPrompt")
local lightSound = Main:WaitForChild("LightSwitchSound")

local HeartBeatConn

local switch = true

lightPrompt.Triggered:Connect(function()
	lightSound:Play()
	if switch == true then
		switch = false
		Sound.Looped = true
		Sound:Play()
		Light.Parent.Material = Enum.Material.Neon
		Light.Enabled = true
		Switch.Orientation = Vector3.new(55, 180, 180)
		lightPrompt.ActionText = "Turn Lights On"
		HeartBeatConn = RunService.Heartbeat:Connect(function()
			print("flickering")
			-- Need to reference the light and sound properties
			local currentLoudness = Sound.PlaybackLoudness
			Light.Angle = Light.Angle - currentLoudness * 5
			Light.Parent.Transparency = Light.Parent.Transparency + currentLoudness / 10
			wait(0.05)
			Light.Angle = originalAngle
			Light.Parent.Transparency = originalTransparency
		end)
	else
		switch = true
		Switch.Orientation = Vector3.new(55, 180, 180)
		lightPrompt.ActionText = "Turn Lights On"
		HeartBeatConn:Disconnect() -- stop the heartbeat updating
	end
end)

Then the only issue now, is that light is on when player joins?

And you want to run the heartbeat, the sound play, flickering etc, to run since the start? and when player clicks to turn off, stop the heartbeat, etc, when player activate prompt again, activate light, music stuff again? And using that script?

Just change some variables and run the function on first script run

local RunService = game:GetService("RunService")

local Light = workspace.Office.Light.Bulb.SpotLight
local Sound = workspace.Office.Light.FlickeringLightSound

local originalAngle = Light.Angle
local originalTransparency = Light.Parent.Transparency

local lightSwitch = workspace.Office:WaitForChild("Lightswitch")
local Switch = lightSwitch:WaitForChild("Switch")
local Main = lightSwitch:WaitForChild("Main")
local lightPrompt = Main:WaitForChild("LightSwitchPrompt")
local lightSound = Main:WaitForChild("LightSwitchSound")

local HeartBeatConn

local switch = false

local function HandleLight()
	if not switch then
		switch = true
		Sound.Looped = true
		Sound:Play()
		Light.Parent.Material = Enum.Material.Neon
		Light.Enabled = true
		Switch.Orientation = Vector3.new(55, 180, 180)
		lightPrompt.ActionText = "Turn Lights On"
		HeartBeatConn = RunService.Heartbeat:Connect(function()
			print("flickering")
			-- Need to reference the light and sound properties
			local currentLoudness = Sound.PlaybackLoudness
			Light.Angle = Light.Angle - currentLoudness * 5
			Light.Parent.Transparency = Light.Parent.Transparency + currentLoudness / 10
			wait(0.05)
			Light.Angle = originalAngle
			Light.Parent.Transparency = originalTransparency
		end)
	else
		switch = false
		Switch.Orientation = Vector3.new(55, 180, 180)
		lightPrompt.ActionText = "Turn Lights On"
		HeartBeatConn:Disconnect() -- stop the heartbeat updating
	end
end

lightPrompt.Triggered:Connect(HandleLight)
HandleLight()

So the light is on and flickering when I join the game, but now the light switch doesn’t work. By that I mean it doesn’t turn off the flickering light.

You sure you are not mixing the switch value? double check, add some prints when player triggers the prompt, let me check. In my test is working normally

Here’s what I changed: (changed “switch” to “lightStatus” to avoid confusion, also added the print(“Runnign”))

local RunService = game:GetService("RunService")

local Light = workspace.Office.Light.Bulb.SpotLight
local Sound = workspace.Office.Light.FlickeringLightSound

local originalAngle = Light.Angle
local originalTransparency = Light.Parent.Transparency

local lightSwitch = workspace.Office:WaitForChild("Lightswitch")
local Switch = lightSwitch:WaitForChild("Switch")
local Main = lightSwitch:WaitForChild("Main")
local lightPrompt = Main:WaitForChild("LightSwitchPrompt")
local lightSound = Main:WaitForChild("LightSwitchSound")

local HeartBeatConn

local lightStatus = false

local function HandleLight()
	print("Running")
	if not lightStatus then
		lightStatus = true
		Sound.Looped = true
		Sound:Play()
		Light.Parent.Material = Enum.Material.Neon
		Light.Enabled = true
		Switch.Orientation = Vector3.new(55, 180, 180)
		lightPrompt.ActionText = "Turn Lights On"
		HeartBeatConn = RunService.Heartbeat:Connect(function()
			print("flickering")
			-- Need to reference the light and sound properties
			local currentLoudness = Sound.PlaybackLoudness
			Light.Angle = Light.Angle - currentLoudness * 5
			Light.Parent.Transparency = Light.Parent.Transparency + currentLoudness / 10
			wait(0.05)
			Light.Angle = originalAngle
			Light.Parent.Transparency = originalTransparency
		end)
	else
		lightStatus = false
		Switch.Orientation = Vector3.new(55, 180, 180)
		lightPrompt.ActionText = "Turn Lights On"
		HeartBeatConn:Disconnect() -- stop the heartbeat updating
	end
end

lightPrompt.Triggered:Connect(HandleLight)
HandleLight()

So I ran a few test. The light works when you join, but when you flick the switch the light stops flickering but the light is still on and the audio is still playing. The light switch doesn’t move to the off position either.

Oka, let me do the test with your script

robloxapp-20230125-0145318.wmv (3.0 MB) Here’s a video of what I’m seeing right now.

Here’s my models. It’s a folder with the light and light switch. Place the folder in workspace.
OfficeLights.rbxm (16.1 KB)

Here’s the local script too. It goes in StarterPlayerScripts.
FlickeringLightScript.lua (1.5 KB)

There are many details in your script. First the idea of using the heartbeat would be for not using the wait(0.05).

And the way you are changing the light parameters “based” on the Playbackloudness causes the light to have an angle of 0. and stuff that makes the light not really showing

When the heartbeat stops you are not stopping the sound playing too.