Unknown bug in my Red Light, Green Light game

  1. What do you want to achieve?
    Simple Red Light, Green Light game with random map spawns.

  2. What is the issue?
    The first round works perfectly, however when the game restarts, the timer stops at 0:25 and stuck on red light.
    Play: Statues - Roblox (uncopylocked)

  3. What solutions have you tried so far?
    None, I’m not sure what to do.

local Map = game.ReplicatedStorage:FindFirstChild("Maps"):GetChildren()[math.random(1,#game.ReplicatedStorage:FindFirstChild("Maps"):GetChildren())]:Clone()
local NPC = Map:FindFirstChild("NPC")

local ROUND_DURATION_SECONDS = 30

local inRedLight = game:GetService("ReplicatedStorage"):FindFirstChild("InRedLight")
local savedPlayerPositions = {}

local spinTweenInfo = TweenInfo.new(1, Enum.EasingStyle.Linear, Enum.EasingDirection.InOut)

local originalHeadCFrame = NPC.HumanoidRootPart.CFrame

local greenLightHead = game:GetService("TweenService"):Create(NPC.HumanoidRootPart, spinTweenInfo, {
	CFrame = originalHeadCFrame
})

local redLightHead = game:GetService("TweenService"):Create(NPC.HumanoidRootPart, spinTweenInfo, {
	CFrame = originalHeadCFrame * CFrame.Angles(0,math.rad(180),0)
})

function dressCharacterInSuit(character)
	for _, object in pairs(character:GetChildren()) do
		if object:IsA("Shirt") or object:IsA("Pants") or object:IsA("ShirtGraphic") then
			object:Destroy()
		end
	end

	local Shirt = Map:WaitForChild("Settings"):FindFirstChild("Clothing").Shirt
	Shirt:Clone().Parent = character

	local Pants = Map:WaitForChild("Settings"):FindFirstChild("Clothing").Pants
	Pants:Clone().Parent = character

end

function secondsToTimestamp(seconds)
	seconds = math.max(seconds,0)

	local minutes = tostring(math.floor(seconds / 60))
	local leftOverSeconds = tostring(seconds % 60)

	if #leftOverSeconds == 1 then
		leftOverSeconds = "0"..leftOverSeconds
	end
	return tostring(minutes)..":"..leftOverSeconds
end

function logPlayerPositions(players)
	for _, player in pairs(players) do
		if player.Character then
			local humRootPart = player.Character:FindFirstChild("HumanoidRootPart")
			if humRootPart then
				savedPlayerPositions[player] = humRootPart.Position
			end
		end
	end
end

function startGame()
	
	greenLightHead:Play()
	inRedLight.Value = false
	savedPlayerPositions = {}


	local playersInRound = game:GetService("Players"):GetPlayers()
	local winners = {}
	local spinDelay = 5
	local lastSpin = tick()
	local isPlaying = false
	local endTouch

	if not workspace:FindFirstChild(Map.Name) then
		Map.Parent = workspace
		Map.Name = "Map"
	end

	for _, player in pairs(playersInRound) do

		player.Character:FindFirstChild("HumanoidRootPart").Position = workspace:FindFirstChild(Map.Name):FindFirstChild("StartingSpawn").Position + Vector3.new(0, 3, 0)

		player.PlayerGui:FindFirstChild("ClientUI").Timer.Visible = true
		player.PlayerGui:FindFirstChild("ClientUI").LightStatus.Text = "GREEN LIGHT"
		player.PlayerGui:FindFirstChild("ClientUI").LightStatus.TextColor3 = Color3.fromRGB(0,255,0)

		if not game:GetService("Teams"):FindFirstChild("Playing") then
			local PlayingTeam = Instance.new("Team", game:GetService("Teams"))
			PlayingTeam.Name = "Playing"
			PlayingTeam.TeamColor = BrickColor.new("Really black")
			PlayingTeam.AutoAssignable = false

			player.Team = PlayingTeam
		end

		if workspace:FindFirstChild(Map.Name):WaitForChild("Settings"):FindFirstChild("Clothing").Enabled.Value == true then
			dressCharacterInSuit(player.Character)
		end

	end

	endTouch = Map.EndBarrier.Touched:Connect(function(toucher)
		if not toucher or not toucher.Parent then isPlaying = false
			return
		end

		local touchChar = toucher.Parent
		local touchPlayer = game:GetService("Players"):GetPlayerFromCharacter(touchChar)

		if touchPlayer then

			local winnersIndex = table.find(winners,touchPlayer)
			if winnersIndex then return end

			table.insert(winners,touchPlayer)
			local playerIndex = table.find(playersInRound,touchPlayer)
			if playerIndex then
				table.remove(playersInRound,playerIndex)
			end
		end
	end)

	Map.StartBarrier.Touched:Connect(function()
		if isPlaying == false then isPlaying = true end
	end)

	for i = ROUND_DURATION_SECONDS, 0, -1 do

		for _, player in pairs(playersInRound) do
			if #playersInRound >= 1 then
				player.PlayerGui:FindFirstChild("ClientUI").Timer.Text = secondsToTimestamp(i)
				player.PlayerGui:FindFirstChild("ClientUI").Timer.Visible = true
			end
		end

		if inRedLight.Value then
			for player, savedPosition in pairs(savedPlayerPositions) do
				if player.Character then

					local winnerIndex = table.find(winners,player)
					if winnerIndex then
						continue
					end

					local humRootPart = player.Character:FindFirstChild("HumanoidRootPart")
					if humRootPart then
						if (humRootPart.Position-savedPosition).Magnitude >= 1 and isPlaying == true then
							isPlaying = false

							player:LoadCharacter()

							savedPlayerPositions[player] = nil

							local playerIndex = table.find(playersInRound,player)
							if playerIndex then
								table.remove(playersInRound,playerIndex)

								if not game:GetService("Teams"):FindFirstChild("Spectating") and isPlaying == false then
									local SpectatingTeam = Instance.new("Team", game:GetService("Teams"))
									SpectatingTeam.Name = "Spectating"
									SpectatingTeam.TeamColor = BrickColor.new("Grey")
									SpectatingTeam.AutoAssignable = false

									player.Team = SpectatingTeam
								end
							end
						end
					end
				end
			end
		end

		if tick()-lastSpin >= spinDelay then
			if inRedLight.Value == true then
				inRedLight.Value = false
				greenLightHead:Play()
			else
				inRedLight.Value = true
				redLightHead:Play()
				redLightHead.Completed:Wait()
				logPlayerPositions(playersInRound)
			end
			lastSpin = tick()
			spinDelay = spinDelay * 0.95
		end

		if #playersInRound == 0 then

			for _, player in pairs(game:GetService("Players"):GetPlayers()) do
				player.PlayerGui:FindFirstChild("ClientUI").Timer.Text = "NO SURVIVORS"
				player.PlayerGui:FindFirstChild("ClientUI").Timer.TextColor3 = Color3.fromRGB(255, 255, 255)

				player.PlayerGui:FindFirstChild("ClientUI").LightStatus.Text = "GAME OVER"
				player.PlayerGui:FindFirstChild("ClientUI").LightStatus.TextColor3 = Color3.fromRGB(255,0,0)
				
				task.wait(5)
				player.PlayerGui:FindFirstChild("ClientUI").Timer.Visible = false
				
			end

			task.wait()
			break
		end

		if secondsToTimestamp(i) == "0:00" then

			for _, player in pairs(playersInRound) do
				player:LoadCharacter()
				
				player.PlayerGui:FindFirstChild("ClientUI").Timer.Text = "RAN OUT OF TIME"
				player.PlayerGui:FindFirstChild("ClientUI").Timer.TextColor3 = Color3.fromRGB(255, 255, 255)

				for _, players in pairs(game:GetService("Players"):GetPlayers()) do
					players.PlayerGui:FindFirstChild("ClientUI").LightStatus.Text = "GAME OVER"
					players.PlayerGui:FindFirstChild("ClientUI").LightStatus.TextColor3 = Color3.fromRGB(255,0,0)
				end
				task.wait(5)
				player.PlayerGui:FindFirstChild("ClientUI").Timer.Visible = false

			end
			
			task.wait()
			break
		end

		task.wait(1)
	end

	endTouch:Disconnect()

	for _, winner in pairs(winners) do

		if winner.Character then

			if not game:GetService("Teams"):FindFirstChild("Winners") then
				local WinningTeam = Instance.new("Team", game:GetService("Teams"))
				WinningTeam.Name = "Winners"
				WinningTeam.TeamColor = BrickColor.new("Bright green")
				WinningTeam.AutoAssignable = false

				winner.leaderstats.WINS.Value += 1
				winner.Team = WinningTeam
			end

		end
	end
end

while true do

	for _, player in pairs(game:GetService("Players"):GetPlayers()) do
		player.PlayerGui:FindFirstChild("ClientUI").LightStatus.Text = "INTERMISSION"
		player.PlayerGui:FindFirstChild("ClientUI").LightStatus.TextColor3 = Color3.fromRGB(255, 255, 255)
	end
	
	if workspace:FindFirstChild(Map.Name) then
		workspace:FindFirstChild(Map.Name):Destroy()
		Map = game.ReplicatedStorage:FindFirstChild("Maps"):GetChildren()[math.random(1,#game.ReplicatedStorage:FindFirstChild("Maps"):GetChildren())]:Clone()
	end

	for _, Team in pairs(game:GetService("Teams"):GetChildren()) do
		Team:Destroy()
	end

	task.wait(15)
	startGame()

end

GUI:

game:GetService("ReplicatedStorage").InRedLight.Changed:Connect(function(inRedLight)
	if inRedLight then
		script.Parent.LightStatus.Text = "RED LIGHT"
		script.Parent.LightStatus.TextColor3 = Color3.fromRGB(255,0,0)
		workspace.Map.StartLine.BrickColor = BrickColor.new(255, 0, 0)
		script.Indicator.PlaybackSpeed = 0.5
		script.Indicator:Play()
	else
		script.Parent.LightStatus.Text = "GREEN LIGHT"
		script.Parent.LightStatus.TextColor3 = Color3.fromRGB(0,255,0)
		workspace.Map.StartLine.BrickColor = BrickColor.new(0, 255, 0)
		script.Indicator.PlaybackSpeed = 1.3
		script.Indicator:Play()
	end
end)

The first thing i want to say is your code is not efficient at all, especially with preformance, things like these can cause memory leaks which will cause your game to become laggier as time goes on.

I recommend you start using module scripts and consider finding ways to clean your code. I format my code like this always :

--// Services
local replicatedStorage = game:GetService('ReplicatedStorage')
local playerService = game:GetService('Players')

--// Modules
local modulesFolder = replicatedStorage:WaitForChild('Modules')
local dataSaver = require(modulesFolder:WaitForChild('DataSaver'))

--// Functions
function playerJoined(plr:Player)
	dataSaver.createFolder(plr) -- creates a folder and loads the data
end

function playerLeaving(plr:Player)
	dataSaver.saveData(plr)
end

--// Connections

playerService.PlayerAdded:Connect(playerJoined)

playerService.PlayerRemoving:Connect(playerLeaving)

game:BindToClose(function()
	for _,plr in pairs(playerService:GetPlayers()) do
		playerLeaving(plr)
	end
end)

My code is much more easier to read and locate mistakes, most of your time when coding is reading your code, so if its not readable make it readable. Here’s a format i always follow

--// Services
--// Modules
--// Objects
--// Values
--// Functions
--// Connections

THE PROBLEMS

Please always consider looking at your console in studio and in game!.

For the gui issue, on the first liner under the function put

if not workspace:FindFirstChild('Map') then return end

This means you should check if there are any constant values that should change but dont, meaning there are places your either forgot to fill or didn’t know how to fill.

If checking all your code that all the values are being updated and is checking if the ‘Map’ is there then please reply again!

1 Like

I tracked through your code using print statements and the Output window.

I found the moment where it stops on round 2.

Screen Shot 2024-04-17 at 1.50.57 PM

I deleted lines 178 and 179 then pressed play.

Round 2 counted down fully as it should.

So, you need to figure out why redLightHead.Completed:Wait() is causing an issue.

1 Like

You’re right, I’m going to rewrite everything and make it easier for myself, I’ve had this game sitting in the dust for a while, so the code itself is old. But thank you for making me realize that.

1 Like