GUI won't load on client even though it prints that it is

I’m trying to update the Wave GUI in my zombie game, and there’s a problem.

For some reason, when the round ends, from using the EndRound() function, the Wave GUI updating just stops working, and it never shows up again.

What’s interesting is that the functions that update the Wave GUI on the client side prints that the Wave GUI is visible, and it accurately prints the info of the wave, yet the Wave GUI is invisible and when I do make it visible manually during testing, it doesn’t update. This may be something to do with client and server communication, because the client side prints that it’s working but it’s not.

I tried moving around the Wave GUI remote event callings, but that didn’t work, and I couldn’t really find anything related to this issue.

Here's the Wave Module
--MODULE--
local WavesModule = {}


--PRIVATE FUNCTIONS--

--Constant spawning of zombies
local function ZombieSpawning()
	
	--VARIABLES--
	
	--LOGIC--
	
	--Loop through zombie queue and spawn zombies
	for i, zombieName in ipairs(Global_Info.ZombieQueue) do
		
		--Make sure the function should run
		if Global_Info.RoundInfo.Active == false or not CurrentMapFolder:FindFirstChildWhichIsA("Model") or not CurrentMapFolder:FindFirstChildWhichIsA("Model"):FindFirstChild("ZombieSpawns") then return end
		
		
		--VARIABLES--
		
		local CurrentMap = CurrentMapFolder:FindFirstChildWhichIsA("Model")
		local ZombieSpawns = CurrentMap:FindFirstChild("ZombieSpawns")
		
		
		--LOGIC--
		
		--Spawn zombie	
		ZombieSpawnModule.IndividualSpawn(ZombieInfoModule.Info[zombieName], ZombieSpawns:GetChildren()[math.random(#ZombieSpawns:GetChildren())], Global_Info.Entrances)
		Global_Info.ZombieQueue[i] = nil
		
		--Cooldown
		task.wait(Global_Info.RoundInfo.ZombieSpawnCooldown)
		
	end
		
end



--Wave
local function Wave()
	
	--Make sure function should run
	if Global_Info.RoundInfo.Active == false or not CurrentMapFolder:FindFirstChildWhichIsA("Model") or not CurrentMapFolder:FindFirstChildWhichIsA("Model"):FindFirstChild("ZombieSpawns") then return end
		
	
	--VARIABLES--
	
	--Wave Info Variables
	local CurrentWave = Global_Info.RoundInfo.CurrentWave
	
	--Map variables
	local CurrentMap = CurrentMapFolder:FindFirstChildWhichIsA("Model")
	
	local PlayerSpawns = CurrentMap:FindFirstChild("PlayerSpawns")
	
	
	--LOGIC--
	
	-----------------Back End-----------------
	
	--Wave Event
	local WaveThread = coroutine.create(function()
		
		--Start Event if there is one
		WaveEventModule.StartEvent(WaveEventModule.chooseEvent())
		
		--Spawn zombies
		ZombieSpawning()
		
	end)
	
	--Spawn in zombies
	task.spawn(WaveThread)
	table.insert(Global_Info.RoundInfo.ZombieSpawningThreads, WaveThread)
	
	
	--Increase zombie rarity for next round
	ZombieInfoModule.IncreaseRarity()
	
	
	-----------------Front End-----------------

	--Wave Gui Display
	UpdateWave_RemoteEvent:FireAllClients(Global_Info.RoundInfo.CurrentWave, Global_Info.RoundInfo.RequiredZombies)
	
	-------------------------------------------
	
	
	--If all zombies spawn, wait until all required zombies are eliminated or all players lose
	repeat task.wait(0.1) until Global_Info.RoundInfo.RequiredZombies <= 0 or #DeployedTeam:GetPlayers() <= 0
	
	
	--Make sure that all threads are closed before the next wave
	for _, thread in pairs(Global_Info.RoundInfo.ZombieSpawningThreads) do
		coroutine.close(thread)
		thread = nil
	end
	
	
	--End wave event if there is one
	WaveEventModule.EndEvent()
	
end


--Transition
local function Transition()
	
end


--Boss
local function Boss()
	
	--VARIABLES--
	
	--Wave Info Variables
	local CurrentWave = Global_Info.RoundInfo.CurrentWave
	
	--LOGIC--
	
	--Load Arena
	LoadModule.LoadBossStage(BossArenas:GetChildren()[math.random(#BossArenas:GetChildren())])

end


------------------------------------------
------------------------------------------


--PUBLIC FUNCTIONS--

--Start the round
function WavesModule.StartRound()
	
	--TEMPORARY
	------------------------------------------------------------------------
	for _, plr in pairs(game.Players:GetPlayers()) do
		plr.Team = DeployedTeam
	end
	------------------------------------------------------------------------
	
	--VARIABLES--
	
	--Wave Info--
	Global_Info.RoundInfo.Active = true
	
	
	--LOGIC--
	
	
	--CONFIGURE
	
	--Load Map
	LoadModule.LoadRound(Maps:GetChildren()[math.random(#Maps:GetChildren())])
	
	-----------------Front End-----------------
	
	--GUI
	
	----------------------------------------
	--TEMPORARY (Move to when player is deployed, for each specific player)
	--Start Wave Gui Display
	StartWave_RemoteEvent:FireAllClients(Global_Info.RoundInfo.CurrentWave, Global_Info.RoundInfo.RequiredZombies)
	----------------------------------------
	
	-------------------------------------------
	
	
	--Wait until at least one player is playing
	repeat task.wait(0.1) until #DeployedTeam:GetPlayers() >= 1
	
	
	--Looping through waves--
	while Global_Info.RoundInfo.Active == true do		
		
		--Round Info--
		Global_Info.RoundInfo.CurrentWave += 1 --Increase wave amount by 1
		
				
		if Global_Info.RoundInfo.CurrentWave == 1 then
			Global_Info.RoundInfo.RequiredZombies = 23 --13
			Global_Info.RoundInfo.ZombiesToSpawn = 30 --20
		end
				
		--Add zombies to zombie queue every wave, and reset zombie queue from last wave
		table.clear(Global_Info.ZombieQueue)
		for i = 1, Global_Info.RoundInfo.ZombiesToSpawn, 1 do
			ZombieSpawnModule.AddToZombieQueue(ZombieInfoModule.Info[ZombieSpawnModule.selectZombieByRarity(ZombieInfoModule.Zombie_Rarity)])
		end
				
		
		--Check if it is a boss wave
		if Global_Info.RoundInfo.CurrentWave % 10 == 0 then
				
			Transition() --Transition to next map
				
			--Configure Boss Wave
			
			--Boss()
			
			-------------------------------
			Wave() --TEMPORARY
			-------------------------------
			
			--If no boss (wave 500 or something), then just load another wave
				
		elseif Global_Info.RoundInfo.CurrentWave % 11 == 0 then
			
			Transition() --Transition to next map
			
			--Clear boss and arena, and replace it with next map
			
			
			--Configure Wave
			
			Wave()
				
		else
				
			--Configure Wave
			Wave()
				
		end
		
		
		--Modify values after current wave
		--Global_Info.RoundInfo.ZombiesToSpawn = math.ceil(15 * 1.1^Global_Info.RoundInfo.CurrentWave) --Increases zombies that spawn every wave
		Global_Info.RoundInfo.ZombiesToSpawn = math.ceil(Global_Info.RoundInfo.ZombiesToSpawn * 1.1) --Increases zombies that spawn every wave
		Global_Info.RoundInfo.RequiredZombies = Global_Info.RoundInfo.ZombiesToSpawn - 7 --Increases required zombies every wave		
		Global_Info.RoundInfo.ZombieSpawnCooldown *= 0.95 --Decreases zombie spawning cooldown
		
		
	end
	
	
end



--End the round
function WavesModule.EndRound()

	print("Ending Round")

	--VARIABLES--


	--LOGIC--
	
	--Back End--
	
	--Stop zombies from spawning
	for _, thread in pairs(Global_Info.RoundInfo.ZombieSpawningThreads) do
		coroutine.close(thread)
		thread = nil
	end
	
	--Remove all zombies
	for _, zombie in pairs(Global_Info.Zombies) do
		zombie:removeZombie()
	end
	
	--Stop wave event if there is one
	WaveEventModule.EndEvent()
	
	--Reset Values
	
	--General round values cleared
	table.clear(Global_Info.Zombies)
	table.clear(Global_Info.Entrances)
	table.clear(Global_Info.ZombieQueue)
	
	--Round Info variables reset and cleared
	Global_Info.RoundInfo.Active = false
	Global_Info.RoundInfo.RequiredZombies = 0
	Global_Info.RoundInfo.ZombiesToSpawn = 0
	Global_Info.RoundInfo.ZombieSpawnCooldown = 2
	Global_Info.RoundInfo.CurrentWave = 0
	
	--Reset Rarity Weight
	ZombieInfoModule.Zombie_Rarity = ZombieInfoModule.DefaultZombieRarity
	
	
	-----------------Front End-----------------

	--GUI
	
	----------------------------------------
	--TEMPORARY (Move to when player is deployed, for each specific player)
	--End Wave Gui Display
	EndWave_RemoteEvent:FireAllClients()
	----------------------------------------
	
	-------------------------------------------
	
	
	--Load Lobby
	LoadModule.LoadLobby()


end


------------------------------------------
------------------------------------------


--EVENTS--

--Checks if round should end
DeployedTeam.PlayerRemoved:Connect(function()

	--Checks if all players lost
	if #DeployedTeam:GetPlayers() <= 0 then
		Global_Info.RoundInfo.Active = false
	end
	
end)


--Checks when a zombie is eliminated
CurrentZombies.ChildRemoved:Connect(function()

	--VARIABLES--



	--LOGIC--		

	--Back End--

	--Decreases from required Zombies
	if Global_Info.RoundInfo.RequiredZombies > 0 then
		Global_Info.RoundInfo.RequiredZombies -= 1
		print(Global_Info.RoundInfo.RequiredZombies)
	end


	--Checks if no zombies left
	if #CurrentZombies:GetChildren() <= 0 then

		--Move to next wave handled by Wave function

	end


	-----------------Front End-----------------

	--Update Wave Gui Display
	if Global_Info.RoundInfo.Active == true then
		UpdateWave_RemoteEvent:FireAllClients(Global_Info.RoundInfo.CurrentWave, Global_Info.RoundInfo.RequiredZombies)
	end
	
	-------------------------------------------


end)



--[[TEMPORARY
--------------------------------------
local thread1 = coroutine.create(function()
	while task.wait(1) do
		print(Global_Info.ZombieQueue)
	end
end)
task.spawn(thread1)
--------------------------------------
]]



return WavesModule
Client Side Wave GUI Script
---Listen To Remote Events---

--Wave Event Remote Events
StartWave_RemoteEvent.OnClientEvent:Connect(WaveUpdateModule.StartWave)

EndWave_RemoteEvent.OnClientEvent:Connect(WaveUpdateModule.EndWave)

UpdateWave_RemoteEvent.OnClientEvent:Connect(WaveUpdateModule.UpdateWave)

--Random Wave Event Remote Events
StartRandomWaveEvent_RemoteEvent.OnClientEvent:Connect(RandomWaveEventModule.StartRandomWaveEvent) --Start the wave event

EndRandomWaveEvent_RemoteEvent.OnClientEvent:Connect(RandomWaveEventModule.EndRandomWaveEvent) --End the wave event
Wave Update Module (Used in the Client Sided Script I showed above)

---VARIABLES---

--Player Variables--
local plr = Players.LocalPlayer


--GUI Variables--
local PlayerGui = plr.PlayerGui

--Deployed Gui--
local DeployedGui = PlayerGui:WaitForChild("Deployed")

--Wave Gui
local WaveInfoFrame = DeployedGui:WaitForChild("WaveInfo")

local CurrentWaveLabel = WaveInfoFrame:WaitForChild("CurrentWave")
local RequiredZombiesLabel = WaveInfoFrame:WaitForChild("RequiredZombies")

------------------------------------------
------------------------------------------


--MODULE--
local WaveUpdateModule = {}


--PRIVATE FUNCTIONS--



------------------------------------------
------------------------------------------


--PUBLIC FUNCTIONS--

--Start Wave
function WaveUpdateModule.StartWave(Wave: number, RequiredZombies: number)
	
	print("!!!!!!!!!!!!!!!!!!!!!!!!!!!!   START WAVE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
		
	--VARIABLES--
	
	
	--LOGIC--
	WaveInfoFrame.Visible = true
	
	CurrentWaveLabel.Text = "Wave " .. Wave
	RequiredZombiesLabel.Text = "Zombies: " .. RequiredZombies
	
	
end


--End Wave
function WaveUpdateModule.EndWave()
	
	print("!!!!!!!!!!!!!!!!!!!!!!!!!!!!   END WAVE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
		
	--VARIABLES--
	

	--LOGIC--
	WaveInfoFrame.Visible = false
	
	CurrentWaveLabel.Text = ""
	RequiredZombiesLabel.Text = ""
	
	
end


--Update Wave
function WaveUpdateModule.UpdateWave(Wave: number, RequiredZombies: number)
	
	print("!!!!!!!!!!!!!!!!!!!!!!!!!!!!   UPDATE WAVE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
		
	--VARIABLES--


	--LOGIC--
	CurrentWaveLabel.Text = "Wave " .. Wave
	RequiredZombiesLabel.Text = "Zombies: " .. RequiredZombies
	
	
end



---------------------------------
--TEMPORARY
local thread1 = coroutine.create(function()
	
	while task.wait(1) do
		print(WaveInfoFrame.Visible)
		print(CurrentWaveLabel.Text)
		print(RequiredZombiesLabel.Text)
	end
	
end)

task.spawn(thread1)
---------------------------------




return WaveUpdateModule

Thanks :happy2:

2 Likes

Idk but i had the same problem, if you are using frames, try using canvas group or screen gui, it might work. It did for me. And if you do it in testing mode, remember to not do it in starter gui, do it in playergui.

I do not think you can access the playergui in a module script since it runs server side. What you can do is pass the local plr object to the endwave function in that client script you got. Like this

EndWave_RemoteEvent.OnClientEvent:Connect(function()
   WaveUpdateModule.EndWave(plr) -- plr is the local player in the local script
end)

Then in ur module script…

function WaveUpdateModule.EndWave(plr)
	
	print("!!!!!!!!!!!!!!!!!!!!!!!!!!!!   END WAVE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
		
	--VARIABLES--
        --GUI Variables--
       local PlayerGui = plr.PlayerGui

        --Deployed Gui--
       local DeployedGui = PlayerGui:WaitForChild("Deployed")

--Wave Gui
       local WaveInfoFrame = DeployedGui:WaitForChild("WaveInfo")

       local CurrentWaveLabel = WaveInfoFrame:WaitForChild("CurrentWave")
       local RequiredZombiesLabel = WaveInfoFrame:WaitForChild("RequiredZombies")	

	--LOGIC--
	WaveInfoFrame.Visible = false
	
	CurrentWaveLabel.Text = ""
	RequiredZombiesLabel.Text = ""
	
	
end

Maybe to optimize this you could have a function to initialize the gui variables but that aint the subject of this post soo yeah.

1 Like

The module script (WaveUpdateModule) is stored in the Starter Player Scripts, which is local. It also works only before the entire round ends (when I lose), and before then it updates everything correctly.

Right after the End Round function is used (or at least when I lose), it never works again until I rejoin…

I think there’s a different problem at play, because it works just fine until the entire round ends

Hmm that’s strange. Why don’t you try putting the client script and the module script in starter gui? Because im stumped if it works before the round ends

1 Like

RESET ON SPAWN WAS ON :rage: :rage: :rage: :rage: :rage:

1 Like

:skull: Well take this as a learning experience

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.