Gui is not valid member of Player1.PlayerGui

I’ve created a module script for a round-based game, HOWEVER, when I tried it in a Local Server, with 2 players, gui ‘Objective’ was not found in the playergui of player1.

local mapFolder = game:GetService("ServerStorage"):WaitForChild("Maps")
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local EventManager = require(game:GetService("ReplicatedStorage"):WaitForChild("EventsManager"))
local badgeAwarder = require(game:GetService("ReplicatedStorage"):WaitForChild("BadgeAwarder"))

local mapMgr = {
	maps = {
		Crossroads = {
			Icon = "rbxassetid://18453859364",
			Name = "Crossroads",
			Model = mapFolder:WaitForChild("Crossroads"),
			Votes = 0
		},
		Crossroads2 = {
			Icon = "rbxassetid://18453859364",
			Name = "Crossroad",
			Model = mapFolder:WaitForChild("Crossroads"),
			Votes = 0
		},
		Crossroads3 = {
			Icon = "rbxassetid://18453859364",
			Name = "Crossroa",
			Model = mapFolder:WaitForChild("Crossroads"),
			Votes = 0
		},
		-- Add more maps here if needed
	},
	currentMap = nil,
	roundTimer = 120,
	intermissionTime = 20,
	votingTime = 20,
	eventInterval = 15,
	phase = "Intermission"
}

function mapMgr:IsMapLoaded()
	return mapMgr.currentMap ~= nil
end

function mapMgr:LoadMap(mapName)
	if mapMgr.currentMap then
		mapMgr.currentMap:Destroy()
		mapMgr.currentMap = nil
	end

	local mapInfo = mapMgr.maps[mapName]
	if mapInfo then
		local mapClone = mapInfo.Model:Clone()
		mapClone.Parent = workspace
		mapMgr.currentMap = mapClone
		print(mapName .. " has been loaded.")
	else
		warn("Map " .. mapName .. " does not exist in the map manager.")
	end
end

function mapMgr:UnloadMap()
	if mapMgr.currentMap then
		mapMgr.currentMap:Destroy()
		mapMgr.currentMap = nil
		local plrList = Players:GetChildren()
		for _, plr in pairs(plrList) do
			if plr:IsA("Player") then
				plr:LoadCharacter()
			end
		end
	end
end

function mapMgr:StartIntermission()
	local plrList = Players:GetChildren()
	mapMgr.phase = "Intermission"
	mapMgr.intermissionTime = 5
	while mapMgr.intermissionTime >= 0 do
		for _, plr in pairs(plrList) do
			if plr:IsA("Player") then
				local gui = plr.PlayerGui
				gui.Objective.Enabled = true
				gui.Objective.TextRandom.Text = "Intermission"
				gui.Objective.Time.Text = tostring(mapMgr.intermissionTime).."s"
			end
		end
		mapMgr.intermissionTime -= 1
		
		task.wait(1)
	end
end

function mapMgr:ResetVotes()
	for _, map in pairs(mapMgr.maps) do
		map.Votes = 0
	end
end

function mapMgr:StartVoting()
	mapMgr.votingTime = 5
	mapMgr.phase = "Voting"
	mapMgr:ResetVotes()
	local plrList = Players:GetChildren()
	task.spawn(function()
		while mapMgr.votingTime >= 0 do
			for _, plr in pairs(plrList) do
				if plr:IsA("Player") then
					local gui = plr.PlayerGui
					gui.Objective.Enabled = false
					gui.Vote.Time.Text = tostring(mapMgr.votingTime).."s"
					
					end
				end
			task.wait(1)
			mapMgr.votingTime -= 1
			end

		end)
	
	local mapKeys = {}
	for key, _ in pairs(mapMgr.maps) do
		table.insert(mapKeys, key)
		task.wait(0.1)
	end
	
	-- Ensure there are enough maps to choose from
	if #mapKeys < 3 then
		warn("Not enough maps available for voting.")
		return
	end
	
	local selectedMaps = {}
	for i = 1, 3 do
		local index = math.random(1,#mapKeys)
		table.insert(selectedMaps, mapKeys[index])
		table.remove(mapKeys, index)
	end
	
	-- Display the voting GUI and allow players to vote
	for _, plr in pairs(Players:GetPlayers()) do
		local gui = plr:WaitForChild("PlayerGui"):WaitForChild("Vote")
		gui.Enabled = true
		plr:SetAttribute("Voted", false)

		for i, mapName in ipairs(selectedMaps) do
			local choice = gui.List:FindFirstChild("Choice" .. i)
			if not choice then
				choice = gui.Choice:Clone()
				choice.Name = "Choice" .. i
				choice.Parent = gui.List
				choice.Visible = true
			end

			local mapInfo = mapMgr.maps[mapName]
			choice.MapImage.Image = mapInfo.Icon
			choice.MapName.Text = mapInfo.Name
			choice.VoteAmount.Text = "0"

			choice.VoteButton.MouseButton1Click:Connect(function()
				if mapMgr.phase == "Voting" then
					if plr:GetAttribute("Voted") then return end
					plr:SetAttribute("Voted",true)
					mapInfo.Votes = mapInfo.Votes + 1
					choice.VoteAmount.Text = tostring(mapInfo.Votes)
				end
			end)
		end
	end
		task.wait(mapMgr.votingTime)

		-- Determine the map with the most votes
		local winningMap = selectedMaps[1]
		for _, mapName in pairs(selectedMaps) do
			if mapMgr.maps[mapName].Votes > mapMgr.maps[winningMap].Votes then
				winningMap = mapName
			end
		end

		-- Load the winning map
		mapMgr:LoadMap(winningMap)

		for _, plr in pairs(Players:GetPlayers()) do
			local gui = plr:WaitForChild("PlayerGui"):WaitForChild("Vote")
			gui.Enabled = false
			plr:SetAttribute("Voted", false)
	end
end

function mapMgr:AwardPlayers(Players)
	local plrTable = Players
	for _, play in pairs(plrTable) do
		if play:IsA("Player") then
			local leaderstats = play:WaitForChild("leaderstats")
			leaderstats.Wins.Value += 1
			if leaderstats.Wins.Value >= 1 then
				badgeAwarder:awardBadge(play.UserId, 3362131244097121)
			end
			if leaderstats.Wins.Value >= 10 then
				badgeAwarder:awardBadge(play.UserId, 3696060825482873)
			end
			if leaderstats.Wins.Value >= 25 then
				badgeAwarder:awardBadge(play.UserId, 4380719369476841)
			end
			if leaderstats.Wins.Value >= 50 then
				badgeAwarder:awardBadge(play.UserId, 654041986778175)
			end
		end
	end	
end

function mapMgr:BeginRound()
	local participants = {}
	if mapMgr.currentMap ~= nil then
		local plrList = Players:GetChildren()
		for _, plr in pairs(plrList) do
			if plr:IsA("Player") then
				local gui = plr.PlayerGui
				local objectiveUI = gui:WaitForChild("Objective")
				objectiveUI.Enabled = true

				local character = plr.Character or plr.CharacterAdded:Wait()
				local spawnpoints = mapMgr.currentMap:FindFirstChild("SpawnPoints"):GetChildren()

				character:WaitForChild("HumanoidRootPart").CFrame = spawnpoints[math.random(1, #spawnpoints)].CFrame
				table.insert(participants, plr)
			end
		end

		mapMgr.roundTimer = 120
		local eventCounter = 0
		while mapMgr.roundTimer > 0 do
			for _, plr in pairs(plrList) do
				if plr:IsA("Player") then
					game.Players.PlayerRemoving:Connect(function(plar)
						table.remove(participants,table.find(participants, plar))
					end)
					plr.Character:FindFirstChild("Humanoid").Died:Connect(function()
						table.remove(participants,table.find(participants, plr))		
					end)
					local gui = plr:FindFirstChild("PlayerGui")
					if gui then
						local objectiveUI = gui:WaitForChild("Objective")
						if objectiveUI and objectiveUI:FindFirstChild("Time") then
							objectiveUI.TextRandom.Text = "Survive!"
							objectiveUI.Time.Text = tostring(mapMgr.roundTimer) .. "s"
						end
					end
				end
			end
			wait(1)
			mapMgr.roundTimer = mapMgr.roundTimer - 1
			eventCounter = eventCounter + 1

			if eventCounter >= mapMgr.eventInterval then
				coroutine.wrap(function() EventManager:StartRandomEvent(participants) end)()
				eventCounter = 0
			end
		end
	end
	if #participants ~= 0 then
		local survivors = {}
		for _, survivor in pairs(participants) do
			table.insert(survivors,survivor.Name)
		end
		Instance.new("Message", workspace).Text = table.concat(survivors).." survived!"
		mapMgr:AwardPlayers(participants)
		task.wait(3)
		Instance.new("Message", workspace).Text = ""
	elseif #participants == 0 then
		Instance.new("Message", workspace).Text = "No one survived!"
		task.wait(3)
		Instance.new("Message", workspace).Text = ""
	end
end



return mapMgr

Entire script

Troubling code:

function mapMgr:StartIntermission()
	local plrList = Players:GetChildren()
	mapMgr.phase = "Intermission"
	mapMgr.intermissionTime = 5
	while mapMgr.intermissionTime >= 0 do
		for _, plr in pairs(plrList) do
			if plr:IsA("Player") then
				local gui = plr.PlayerGui
				gui.Objective.Enabled = true
				gui.Objective.TextRandom.Text = "Intermission"
				gui.Objective.Time.Text = tostring(mapMgr.intermissionTime).."s"
			end
		end
		mapMgr.intermissionTime -= 1
		
		task.wait(1)
	end
end

Thing is - everything works during normal testing, but when it’s a local server, it doesn’t.

this is the script managing the game loop:

local Players = game:GetService("Players")
local mapMgr = require(game:GetService("ReplicatedStorage"):WaitForChild("MapsList"))

-- Function to start the game loop
local function startGame()
	while true do
		mapMgr:StartIntermission()

		mapMgr:StartVoting()

		mapMgr:BeginRound()
	end
end

Players.PlayerAdded:Once(startGame)

Update: it now doesn’t work in normal testing too.

Update: a simple waitforchild helped. Up for optimizations and reviews though.