Value being noticed as changed twice?

I know I literally just posted a question lol but I have a script that checks when the gameState value is changed. Then, I have an if statement that checks if the gameState is “InGame”, and it seems to be printing and doing everything in the statement twice. Can anybody explain why?

Server Script with code running twice
game.Players.PlayerAdded:Connect(function(player)
	
	local gameState = game.ReplicatedStorage:WaitForChild("GameState")
	gameState.Changed:Connect(function()
		if gameState.Value == "Intermission" then
			game.ReplicatedStorage:WaitForChild("CloneTypeEvent").OnServerEvent:Connect(function(player,cloneType)
				_G.CloneType = cloneType
			end)
				
			for x=10, 0, -1 do
				if x == 0 then
					gameState.Value = "InGame"
				end
				local remoteEvent = game.ReplicatedStorage:WaitForChild("TimeUntilNextGameEvent")
				remoteEvent:FireClient(player,x)
				wait(1)
			end
		end

		if gameState.Value == "InGame" then
			print("In Game")
			print(_G.CloneType)
			if _G.CloneType == "TwoNormal" then
				print("2 normal clones being made")
				repeat wait() until player.Character ~= nil
				player.Character.Archivable = true
				for x=1, 2, 1 do
					local clone = player.Character:Clone()
					clone.Parent = workspace
					clone.Name = player.Name .. " Clone"
				end
			end
		end
	end)

end)

Since you’ve got the gameState.Changed connection setup inside of the playerAdded connection, you’ll setup a new gameState.Changed connection each time a player joins. Think of moving the gameState.Changed connection outside of the playerAdded connection, or add a variable to store the gameState.Changed connection and check to see if it’s already open.

local gsConn 
game.Players.PlayerAdded:Connect(function(player)
    if not gsConn then
        gsConn= gameState.Changed:Connect(function() --Code
    end
    end)
end)

or, if you just want to leave the gameState.Changed always alive…

gameState.Changed:Connect(function() 
    --Enter code here when state changes
end)

game.Players.PlayerAdded:Connect(function(player)
    --Enter code here for when players join
end)

@SnazpantsMixer was only using the PlayerAdded to get the local Player. How would I make the local player visible to all parts of the script?

EDIT: I made it like this and it’s still repeating twice:

game.Players.PlayerAdded:Connect(function(player)
	_G.LocalPlayer = player
end)
	
	local gameState = game.ReplicatedStorage:WaitForChild("GameState")
	gameState.Changed:Connect(function()
		if gameState.Value == "Intermission" then
			game.ReplicatedStorage:WaitForChild("CloneTypeEvent").OnServerEvent:Connect(function(player,cloneType)
				_G.CloneType = cloneType
			end)
				
			for x=10, 0, -1 do
				if x == 0 then
					gameState.Value = "InGame"
				end
				local remoteEvent = game.ReplicatedStorage:WaitForChild("TimeUntilNextGameEvent")
				remoteEvent:FireClient(_G.LocalPlayer,x)
				wait(1)
			end
		end

		if gameState.Value == "InGame" then
			print("In Game")
			print(_G.CloneType)
			if _G.CloneType == "TwoNormal" then
				print("2 normal clones being made")
				repeat wait() until _G.LocalPlayer.Character ~= nil
				_G.LocalPlayer.Character.Archivable = true
				for x=1, 2, 1 do
					local clone = _G.LocalPlayer.Character:Clone()
					clone.Parent = workspace
					clone.Name = _G.LocalPlayer.Name .. " Clone"
				end
			end
		end
	end)

The gameState variable, is this a stringValue?

By calling .Changed, it listens for any changes to that instance, and in your for loop you’re saying to change the gameState.Value which i believe is triggering your changed event causing it to run twice, but no more than that because you only change it once in your for loop

But that doesn’t really make sense to me because the cloning function should only happen if gameState.Value = InGame. When I manually set the gameState to Intermission on the Server side, it runs the countdown, and then changes the value to InGame after 10 seconds. So why would it be running more than once?

well you could add a debounce

game.Players.PlayerAdded:Connect(function(player)
	_G.LocalPlayer = player
end)
	
	local gameState = game.ReplicatedStorage:WaitForChild("GameState")
        local debounce
	gameState.Changed:Connect(function()
		if gameState.Value == "Intermission" then
			game.ReplicatedStorage:WaitForChild("CloneTypeEvent").OnServerEvent:Connect(function(player,cloneType)
                  debounce = false
				_G.CloneType = cloneType
			end)
				
			for x=10, 0, -1 do
				if x == 0 then
					gameState.Value = "InGame"
				end
				local remoteEvent = game.ReplicatedStorage:WaitForChild("TimeUntilNextGameEvent")
				remoteEvent:FireClient(_G.LocalPlayer,x)
				wait(1)
			end
		end

		if gameState.Value == "InGame" and debounce == false then
                           debounce = true
			print("In Game")
			print(_G.CloneType)
			if _G.CloneType == "TwoNormal" then
				print("2 normal clones being made")
				repeat wait() until _G.LocalPlayer.Character ~= nil
				_G.LocalPlayer.Character.Archivable = true
				for x=1, 2, 1 do
					local clone = _G.LocalPlayer.Character:Clone()
					clone.Parent = workspace
					clone.Name = _G.LocalPlayer.Name .. " Clone"
				end
			end
		end
	end)

Ok I pulled this into studio and I can see what’s going on…

When you’re inside the for loop you change the value to InGame, triggering a changed event, but at the end of your for loop, since the value is changed, it proceeds to the next if statement which is also hit by the triggered event. A debounce could help, but the proper way to fix that exact issue you’re talking about would be to not make two if statements, but make the second gameState.Value check an elseif statement.

Here’s how I modified the code so I could find the answer…

game.Players.PlayerAdded:Connect(function(player)
	_G.LocalPlayer = player
end)

local gameState = game.ReplicatedStorage:WaitForChild("GameState")
gameState.Changed:Connect(function()
	print("Change trigger")
	if gameState.Value == "Intermission" then
		print("A")
		game.ReplicatedStorage:WaitForChild("CloneTypeEvent").OnServerEvent:Connect(function(player,cloneType)
			_G.CloneType = cloneType
		end)

		for x=10, 0, -1 do
			
			print(x)
			if x == 0 then
				print("b")
				gameState.Value = "InGame"
			end
			print("C")
			local remoteEvent = game.ReplicatedStorage:WaitForChild("TimeUntilNextGameEvent")
			remoteEvent:FireClient(_G.LocalPlayer,x)
			wait(1)
		end
	end
print("D")
	if gameState.Value == "InGame" then
		print("In Game")
		print(_G.CloneType)
		if _G.CloneType == "TwoNormal" then
			print("2 normal clones being made")
			repeat wait() until _G.LocalPlayer.Character ~= nil
			_G.LocalPlayer.Character.Archivable = true
			for x=1, 2, 1 do
				local clone = _G.LocalPlayer.Character:Clone()
				clone.Parent = workspace
				clone.Name = _G.LocalPlayer.Name .. " Clone"
			end
		end
		print("E")
	end
end)

pretty much just threw a bunch of print statements in so I could see what’s going on

1 Like
local variable = true
for x = 1,2,1 do
if variable == true then
print("true")
variable = false
end
if variable == false then
print("false")
end
end


this is basically whats happening right?

output:

true
false (x2)

it repeats the false because it passes through the false twice

local variable = true
for x = 1,2,1 do
if variable == true then
print("true")
variable = false
end
print("passed")
if variable == false then
print("false")
end
end


output

true
passed
false
passed
false