Why is everything printing twice?

  1. I’m trying to make a function that gets a UI inside of playerGui so its easier for all scripts to access UI!

  2. for some reason everything is printing twice and when I try to do: global.GetUI(nameOfUI).Activated:Connect(function()
    print(“here”)
    end
    it prints “here” twice and when I call global.GetUI it prints everything twice aswell

  3. I’ve tried looking on the dev forum but I can’t find anything, I also tried changing the function a little but nothing works

Screenshot 2025-02-17 172128
Screenshot 2025-02-17 172133
Screenshot 2025-02-17 172133
What it prints:
image

function module.GetUI(name)
	if not name then warn("No name provided to GetUi function") return end
	local timeStarted = tick()
	repeat 
		for _, v in module.Player:WaitForChild("PlayerGui"):GetDescendants() do
			print(v)
			if v.Name == name then return v end
			task.wait()
		end  
	until tick() - timeStarted >= 10

	return warn(name, "UI not found after 10 seconds")
end
module.YieldUI = function(name)
	local pgui = module.Player.PlayerGui
	while true do
		local find = pgui:FindFirstChild(name, true)
		if find then
			return find
		else
			pgui.DescendantAdded:Wait()
		end
	end
end

(edit changed from WaitForChild(“PlayerGui”) to PlayerGui)

2 Likes

I honestly don’t know the issue from just looking, it’s probably something to do with use of return and repeat, and I can’t remember the priority for these off the top of my head.

  • Either way, there is a much more efficient way to do this.
  • Currently you are looping a function but also giving a tick limit, which I honestly can’t comprehend what this is supposed to be for.

I’d suggest this VERY COMPLICATED and ADVANCED solution.

  • step 1) DELETE everything past if not name...
  • step 2) insert return module.Player.PlayerGui:FindFirstChild(name, true)
  • step 3) lets understand what I just did

findfirstchild with argument 2 = true means it recursively searches for an object with that name throughout all descendants

get rid of waitforchild… playergui always exists! if it doesnt your roblox is broken.

also a loop is just so inefficent. at this point , just manually find the object without this function

2 Likes

@GenericYellowSquid is right on some things. Even in ReplicatedFirst, the PlayerGui already exists and is likely loaded before any client/local script execution.

As for the UI elements, they may or may not be loaded when a script executes. In ReplicatedFirst, it appears they don’t load beforehand.


image
Even in StarterPlayerScripts, my ScreenGui did not get placed into the PlayerGui until later (due to yielding for Character)
If I disable Players.CharacterAutoLoads in studio, the UI elements in StarterGui are never cloned into PlayerGui.

1 Like

Thanks but by the time scripts in playerScripts run will all the UI in playerGui be loaded?

Refer to @hkep 's post. PlayerGUI is loaded nonetheless. If the descendants arent loaded, they will just return nil from the module.

  • If they return nil, you could just keep calling the module…
  • by implementing tick checks, you are doing 10x the work. You could just do something like this:
local guiobj = nil
repeat
  guiobj = module:GetUI("Name here"); task.wait()
until guiobj

because being honest, if the gui isn’t loaded upon game start within a couple ten milliseconds, there are probably greater issues at hand like why it should take that long for a PC to load a few hundred pixels

1 Like

I wouldn’t use that solution, as it yields unnecessarily.
If I wanted to yield for 10 guis that would call task.wait() 10 times in a row in addition to writing extra code outside of a function call.

For reference, task.wait() will yield RunService.Heartbeat at the minimum. This would result in ~ 10 frame = 0.17s yield. The code works but is slow and can be faster.

surely yours was more efficient overall, but i want him to understand that not everything is one giant math problem; unless hes requiring these GUIs within the first 100ms of the server opening then they will exist on the client nonetheless.

but yeah, my solution is definitely not the most efficient.

however, i do believe task.wait() is .017s not .17 because task.wait() is just one frame right?

yes it’s one frame. I said if you ran your code 10 times:

local function yield_ui(name)
	local guiobj = nil
	repeat
		guiobj = module:GetUI("Name here")
		task.wait()
	until guiobj
	return guiobj
end

local frame1 = yield_ui("Frame1")
local frame2 = yield_ui("Frame2")
-- repeat until frame10

As an example if a script needed 10 different UI elements (with unique names).

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