While loop doesnt break

  1. What do you want to achieve? Keep it simple and clear!
    If the crossroad is active it should break the loop for the white light. And it should run the loop again when false.

  2. What is the issue?
    It doesnt break the loop.

  3. What solutions have you tried so far? Did you look for solutions on the Developer Hub?
    Yes, but they didn’t work

The red lights work with a variable that gives a boolean if its active or not. So i check if its false so the white light turns on. Each light has it own script in the part itself.

White light:

local sourceLight = script.Parent
local lightCover = sourceLight.Parent:GetChildren()
local crossroadActive = game.Workspace.CrossroadLight.Active.Value

local lightStart = game.Workspace.LightCheck
local lightStop = game.Workspace.LightStop

local TweenService = game:GetService("TweenService")

local whiteLight = {Color = Color3.fromRGB(216, 216, 216)}

local offLight = {Color = Color3.fromRGB(29,29,29)}

local info = TweenInfo.new(0.75, Enum.EasingStyle.Circular, Enum.EasingDirection.InOut, 0, false, 0)



while crossroadActive == false do
	wait(0.75)
	local tweenLightToWhite = TweenService:Create(sourceLight, info, whiteLight)
	tweenLightToWhite:Play()
	sourceLight.SpotLight.Enabled = true
	wait(0.75)
	local tweenLightToOff = TweenService:Create(sourceLight, info, offLight)
	tweenLightToOff:Play()
	sourceLight.SpotLight.Enabled = true
	
	if crossroadActive then
		break
	end
end

The two red lights have almost the same script (only difference is the wait):

local lightStart = game.Workspace.LightCheck
local lightStop = game.Workspace.LightStop

local TweenService = game:GetService("TweenService")

local redLight = {Color = Color3.fromRGB(255,0,0)}
local redCover = {Color = Color3.fromRGB(0,0,0)}

local offLight = {Color = Color3.fromRGB(29,29,29)}
local offCover = {Color = Color3.fromRGB(65,65,65)}

local info = TweenInfo.new(0.5, Enum.EasingStyle.Circular, Enum.EasingDirection.InOut, 0, false, 0)



lightStart.Touched:Connect(function(otherPart)
	local humanoid = otherPart.Parent:FindFirstChildWhichIsA("Humanoid")
	if humanoid and crossroadActive == false then
		crossroadActive = true
		wait(0.5)
		while crossroadActive do
			wait(0.5)
			for i,v in pairs(lightCover) do --transition to red
				sourceLight.SpotLight.Enabled = true
				if v.Name == "SourceLight" then
					local tweenLightToRed = TweenService:Create(v, info, redLight)
					tweenLightToRed:Play()
				else
					local tweenCoverToRed = TweenService:Create(v, info, redCover)
					tweenCoverToRed:Play()
				end
			end
			wait(0.5)
			for i,v in pairs(lightCover) do --transition to off
				sourceLight.SpotLight.Enabled = false
				if v.Name == "SourceLight" then
					local tweenLightToOff = TweenService:Create(v, info, offLight)
					tweenLightToOff:Play()
				else
					local tweenCoverToOff = TweenService:Create(v, info, offCover)
					tweenCoverToOff:Play()
				end
			end
		end
	end
end)

lightStop.Touched:Connect(function(otherPart)
	local humanoid = otherPart.Parent:FindFirstChildWhichIsA("Humanoid")
	if humanoid then
		crossroadActive = false
	end
end)```

Thanks in advance!

Try instead:

if crossroadActive == false then

--or

if not crossroadActive then

No, it should break when it’s active. So when its true the white light should stop blinking.

1 Like
if crossroadActive == true then

^ If crossroadActive becomes true, then the while loop won’t run because it only runs when crossroadActive is false.

Try using this:

while wait() do
	if not crossroadActive then
		--Put the things you want to happen when crossroadActive == false

	else
		break --the while loop should break if crossroadActive ~= false
	end
end

The problem is that when you create a base-type variable (strings, numbers, and booleans) it’s value is saved at that time forever.

local crossroadActive = game.Workspace.CrossroadLight.Active.Value

Will always be false until you update it again

crossroadActive = game.Workspace.CrossroadLight.Active.Value

For your situation it is probably best to change the variable declaration to

local crossroadActive: BoolValue = game.Workspace.CrossroadLight.Active

while crossroadActive.Value == false do
    -- etc
end

When you store an instance or table in lua then it is not copied and can be changed by other things like you want.

1 Like

It doesn’t work. Maybe because it runs the loop from the start and the red lights only turn on when its activated.

You are indexing the value at the very beginning

local crossroadActive = game.Workspace.CrossroadLight.Active.Value --> false

Instead:

local crossroadActive = game.Workspace.CrossroadLight.Active

if crossroadActive.Value then
     --> checks if its active at time of check
end

It updates through the script of the red lights. Its off by default. When I touch the part it starts the loop for the red lights and the variable has been set to true. When i touch the other part to stop the red lights the variable goes to false.

I tried to change from Active.Value to Active but it doesnt do anything. Should I change it in the other script from the red lights too?

Yes. If the red lights are a different script then the red light’s crossroadActive is also a different variable. You are making two copies and then editing those copies in isolation. Replace all crossroadActive with crossroadActive.Value

ok i did now i get this. and no error in output

1 Like

Seems good! Now it’s probably just a logical error, in this case it’s because a while loop will only run while the condition is true, after that it will never run again. So while crossroadActive.Value == false do is run at the start and blinks until it’s false then never runs again. I would recommend changing it to something like this


while true do -- true infinite loop
	-- if we shouldn't be running we set it to wait instead
	if crossroadActive.Value == true then
		crossroadActive.Changed:Wait()
		continue
	end

	wait(0.75)
	local tweenLightToWhite = TweenService:Create(sourceLight, info, whiteLight)
	tweenLightToWhite:Play()
	sourceLight.SpotLight.Enabled = true
	wait(0.75)
	local tweenLightToOff = TweenService:Create(sourceLight, info, offLight)
	tweenLightToOff:Play()
	sourceLight.SpotLight.Enabled = true
end

I like using infinite loops with event:Wait() in them so we aren’t constantly checking values.

It works! But now only one red light goes on :confused:

I think I would have to see the explorer tree to help with the red lights. The code looks good to me, my bet is the pairs(lightCover) doesn’t include both of them some how.

This is the explorer:

This is the current code for red light on the right:

local sourceLight = script.Parent
local lightCover = sourceLight.Parent:GetChildren()
local crossroadActive = game.Workspace.CrossroadLight.Active

local lightStart = game.Workspace.LightCheck
local lightStop = game.Workspace.LightStop

local TweenService = game:GetService("TweenService")

local redLight = {Color = Color3.fromRGB(255,0,0)}
local redCover = {Color = Color3.fromRGB(0,0,0)}

local offLight = {Color = Color3.fromRGB(29,29,29)}
local offCover = {Color = Color3.fromRGB(65,65,65)}

local info = TweenInfo.new(0.5, Enum.EasingStyle.Circular, Enum.EasingDirection.InOut, 0, false, 0)



lightStart.Touched:Connect(function(otherPart)
	local humanoid = otherPart.Parent:FindFirstChildWhichIsA("Humanoid")
	if humanoid and crossroadActive.Value == false then
		crossroadActive.Value = true
		wait(0.5)
		while crossroadActive.Value do
			wait(0.5)
			for i,v in pairs(lightCover) do --transition to red
				sourceLight.SpotLight.Enabled = true
				if v.Name == "SourceLight" then
					local tweenLightToRed = TweenService:Create(v, info, redLight)
					tweenLightToRed:Play()
				else
					local tweenCoverToRed = TweenService:Create(v, info, redCover)
					tweenCoverToRed:Play()
				end
			end
			wait(0.5)
			for i,v in pairs(lightCover) do --transition to off
				sourceLight.SpotLight.Enabled = false
				if v.Name == "SourceLight" then
					local tweenLightToOff = TweenService:Create(v, info, offLight)
					tweenLightToOff:Play()
				else
					local tweenCoverToOff = TweenService:Create(v, info, offCover)
					tweenCoverToOff:Play()
				end
			end
		end
	end
end)

lightStop.Touched:Connect(function(otherPart)
	local humanoid = otherPart.Parent:FindFirstChildWhichIsA("Humanoid")
	if humanoid then
		crossroadActive.Value = false
	end
end)



Right. What might be easiest is to copy the script into LightLeft.Light.SourceLight as it is.

Could also try this script, which is fragile if you change the CrossroadLights’ children

local sourceLight = script.Parent
local lightCover = sourceLight.Parent:GetChildren()
-- we walk all the way up parent after parent to LeftLight to get it's children
-- it's fragile because of how many parent's we have to go through
for _, leftChild in ipairs(sourceLight.Parent.Parent.LeftLight.Light:GetChildren()) do
    table.insert(lightCover, leftChild)
end

It should then change all the lights and covers for both sides, but I may have counted the parent’s wrong.

The fragile script works but there is no delay between the two red lights. Copying the script didn’t work. I also change the sourceLight to game.workspace… but now only the right light goes on…

A nasty trick you could use with the fragile script is to change both for loop like so. You will have to adjust other waits, I think just removing the wait(0.5) in-between for loops will do.

sourceLight.SpotLight.Enabled = true
for i,v in pairs(lightCover) do --transition to red
	-- delay the other half of our list (hopefully the left side)
	if i == #lightCover/2 then
		task.wait(0.5)
	end

	if v.Name == "SourceLight" then
		local tweenLightToRed = TweenService:Create(v, info, redLight)
		tweenLightToRed:Play()
	else
		local tweenCoverToRed = TweenService:Create(v, info, redCover)
		tweenCoverToRed:Play()
	end
end

I’ll have to go now but i really appreciate your help. Thanks in advance

1 Like

Hmm only the right red light goes on but doesnt blink. Never thought it would be this complicated…