Looping through GUI does not list all of the items

I have a SurfaceGui and a script that generates upgrades for that surface gui for them to be displayed to the player and also a heartbeat loop in that script that has to update stats for the all of the upgrades in the surface gui every dozen of a second. The problem is that that loop only detects and prints out UIListLayout which was originally there, but it doesnt detect newly created frames. I tried different ordering of the script and using while loop but it doesnt seem to work either. I have no idea how to fix this so any help would be appreciated, and sorry for the poor explanation. Here’s the code:

for Name, Upgrade in pairs(Upgrades) do
	local UpgradeMenu = script.Upgrade:Clone()

	UpgradeMenu.Name = Name
	UpgradeMenu.Parent = BoardUI.Board
	UpgradeMenu.UpgradeName.Text = Upgrade.Name

	UpdateUpgrade(Name, Upgrade, UpgradeMenu)

	UpgradeMenu.BuyButton.MouseButton1Down:Connect(function()
		Remotes.MakeUpgrade:InvokeServer(Name)
	end)
end

RunService.Heartbeat:Connect(function()
	for _, UpgradeMenu in pairs(script.Parent.BoardUI.Board:GetChildren()) do
		print(UpgradeMenu.Name) --> only the UIListLayout
		if not UpgradeMenu:IsA("Frame") then return end
		UpdateUpgrade(UpgradeMenu.Name, Upgrades[UpgradeMenu.Name], UpgradeMenu)
	end
end)

I’m not sure if this is the issue but SERVER scripts cannot detect client instances

1 Like

i understand this but this is all in a client script located in the screen gui, and why would i do this in a server script

Why are you using a loop to create upgrades? First thing’s first, lets clean up and introduce some functions, instead of having to reintroduce the same code over and over.

It would also help if you told us how they got updated, as then you could use better practices such as a .Changed event.


function InitializeUpgrades()
	for Name, Upgrade in pairs(Upgrades) do
		local UpgradeMenu = script.Upgrade:Clone()

		UpgradeMenu.Name = Name
		UpgradeMenu.Parent = BoardUI.Board
		UpgradeMenu.UpgradeName.Text = Upgrade.Name

		UpdateUpgrade(Name, Upgrade, UpgradeMenu)

		UpgradeMenu.BuyButton.MouseButton1Down:Connect(function()
			Remotes.MakeUpgrade:InvokeServer(Name)
		end)
	end
end

local LeakWrap = coroutine.wrap(function() -- Not always necessary, but running in a seperate thread will allow code under the RunService to run
	RunService.Heartbeat:Connect(function()
		for _, UpgradeMenu in pairs(BoardUI.Board:GetChildren()) do -- Make sure you're using the same as you parented previous, might cause issues
			if not string.find(string.lower(UpgradeMenu.ClassName, "ui")) then -- Much better practice, so you could get rid of any UI modifiers, and only focus on what you wish for
				UpdateUpgrade(UpgradeMenu.Name, Upgrades[UpgradeMenu.Name], UpgradeMenu)
			end
		end
	end)
end)

InitializeUpgrades()
LeakWrap()

Get back to us with these questions, try these new practices, and try to post a video / GIF of what exactly is happening, as I am myself a tad confused.

1 Like

Hello! Thank you so much for the reply! The way the get updated cannot be made trough .Changed event, so sadly this wont work. And even tho your proposal was very good, for whatever reason that still doesn’t work. For some reason its not just detecting any new parts that are being created after the game starts. Don’t know if that is a bug or a feature that i don’t know about, I found a workaround. The only time I need to update my upgrades now is when someone buys it, so i can just put the update in the mouse button event. I honestly don’t know how didn’t understand this initially, but still thank you so much for the help and all the code you’ve wrote!

1 Like

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