If anybody is interested, I’ve constructed some code that waits for all GUI to load before proceeding. It basically works by taking the StarterGui’s instances and comparing them to the local player’s PlayerGui and confirming that they match exactly. Use in a LocalScript. Any modifications, criticisms, or ideas are welcome.
local player = game.Players.LocalPlayer;
waitForGui = function(gui)
if not player:WaitForChild("PlayerGui"):findFirstChild(gui, true) then
while not player:WaitForChild("PlayerGui"):findFirstChild(gui, true) do wait() end
end
for _, v in pairs(player:WaitForChild("PlayerGui"):findFirstChild(gui, true):children()) do
waitForGui(v.Name);
end
end
for _, v in pairs(game.StarterGui:children()) do
waitForGui(v.Name);
end
It’s an interesting idea, but at this point you might as well serialise all of your UI elements and construct the UI by script whenever you need it, then you’re sure of what has “loaded” at any point in time. This is what I do in serious projects at least whenever I have a dependency on a particular part of the UI.
Instead of using FindFirstChild with recursive set to true and having waitForGui() semi-recursive (it is recursive, but doesn’t really add much value), change your waitForGui into waitForGui(wanted,obj):
local function waitForGui(wanted,obj)
-- wanted is an object somewhere in StarterGui (including descendants)
-- obj is a "clone" of it as a descendant of some PlayerGui
checkIfAllChildrenArePresent() -- or wait with WaitForChild
-- see if all children of 'wanted' are also in 'obj'
for k,v in pairs(obj:GetChildren()) do
-- we've checked StarterGui.Gui and PlayerGui.Gui
-- it's time to check StarterGui.Gui.Frame and PlayerGui.Gui.Frame
waitForGui(wanted[v.Name],v)
end
end
-- An implementation of the above could be:
local function waitForGui(wanted,obj)
for k,v in pairs(wanted:GetChildren()) do
local found = obj:WaitForChild(v.Name,10)
assert(found,"Took too long to load, something wrong?")
waitForGui(v,found)
end
end