Checking if PlayerGui exists for every single time it needs to be checked

You can write your topic however you want, but you need to answer these questions:

  1. What do you want to achieve? Keep it simple and clear!
    I want to be able to change some values and/or properties inside a player’s GUI without having to have a condition in every single property change.

  2. What is the issue? Include screenshots / videos if possible!
    Whenever I bug test with a large server, it seems multiple of players are running in an issue of certain GUIs not existing because of poor wifi or Roblox not loading in the GUI in time. I have provided some solutions below, but it’s such a hassle to repetitively have these UI’s checked before changing the properties.

  3. What solutions have you tried so far?
    What I have done is check to see if PlayerGui exists in the first place before changing the property. I have also tried making the player load in and only changing the property when the player’s UI is completely loaded.

In summary, I want to know some ways from the community to see if there’s a better (or lazier) way to check if the Player’s GUI has loaded in before changing its properties.

Do you mean PlayerGui container only or PlayerGui and single/multiple Descendants?

Single/multiple descendants. There are times where a UI within the UI was also found as nil in the output

You can build/use a single function to find a child/descendant or even waiting for them to exist so you can call it when you need to retrieve an instance should be in a certain path.

You actually can use this function:

local Player = ...

local function GetInstanceInPath(Player: Player, SubPath: string, WaitForIt: boolean?)
	local FoundInstance = (WaitForIt and Player:WaitForChild("PlayerGui")) or Player:FindFirstChild("PlayerGui")

	local Segments = string.split(SubPath,"\\")
	local Latest

	for _, Segment in ipairs(Segments) do
		if WaitForIt then
			Latest = FoundInstance:WaitForChild(Segment)
		else
			Latest = FoundInstance:FindFirstChild(Segment)
		end
		FoundInstance = Latest
	end
	return FoundInstance
end

local TargetInstance = GetInstanceInPath(Player, "Gui\\TestingGui", false)
1 Like

I will definitely try this in place of my current conditions, I will let you know later if this works and what I am looking for, which from the looks of it, it will work well :+1:

Yo…
I’ve a new more advanced function instead of the last one:

local function GetInstanceFromPath(Ancestor: (Instance | string)?, Path: string, PathSeparator: string?, FunctionTimeout: number?, WaitForCreation: boolean?, InstanceWaitTimeout: number?):(Instance?, string?)
	assert(typeof(Ancestor) == "Instance" or typeof(Ancestor) == "string" or Ancestor == nil, "Invalid Argument [1]; AncestorObject must be an instance.")
	assert(typeof(Path) == "string", "Invalid Argument [2]; String path must be provided.")
	assert(typeof(PathSeparator) == "string" or PathSeparator == nil, "Invalid Argument [3]; String expected.")
	assert(typeof(InstanceWaitTimeout) == "number" or InstanceWaitTimeout == nil, "Invalid Argument [4]; Number expected.")
	assert(typeof(FunctionTimeout) == "number" or FunctionTimeout == nil, "Invalid Argument [5]; Number expected.")
	--------------------------------------------------------------------------------------------------------------------------

	local PathSegments = string.split(Path, (PathSeparator or "\\"))
	local Thread = coroutine.running()
	local FoundInstance

	if typeof(Ancestor) == "Instance" then
		FoundInstance = Ancestor
	elseif typeof(Ancestor) == "string" then
		FoundInstance = game:GetService(Ancestor)
	elseif PathSegments[1] == "game" then
		FoundInstance = game:GetService(table.remove(PathSegments, 2))
		table.remove(PathSegments, 1)
	else
		FoundInstance = game:GetService(table.remove(PathSegments, 1))
	end

	coroutine.wrap(function()
		for _, Segment in ipairs(PathSegments) do
			if WaitForCreation and InstanceWaitTimeout then
				FoundInstance = FoundInstance:WaitForChild(Segment, InstanceWaitTimeout)
			elseif WaitForCreation then
				FoundInstance = FoundInstance:WaitForChild(Segment)
			else
				FoundInstance = FoundInstance:FindFirstChild(Segment)
			end
			if FoundInstance == nil then
				coroutine.resume(Thread, false, "Couldn't find the requested instance.")
				return
			end
		end
		coroutine.resume(Thread, true, FoundInstance)
	end)()

	if FunctionTimeout then
		task.delay(FunctionTimeout, function()
			coroutine.resume(Thread, false, "Timed out while waiting for the instance to be found.")
		end)
	end

	local Success, Response = coroutine.yield(Thread)
	if not Success then return nil, Response end
	return Response::any, nil::any
end
1 Like

Yo thanks for the improved version! I was thinking about replying to this again with some fixed version of the old script, but I didn’t want this to show up on the timeline again since this post is a bit day old. Thanks again :+1:

1 Like

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