Is Gui:WaitForChild() a bad practice?

Hello,

I’ve had a discussion with other developers and we’ve been trying to figure out what is good practice when waiting for gui objects to load.

Here is what I have:

local gui = script.Parent
local frame = gui:WaitForChild("Frame")
local frame1 = frame:WaitForChild("Content"):WaitForChild("Frame1")
local frame2 = frame:WaitForChild("Content"):WaitForChild("Frame2")
local viewportFrame = frame:WaitForChild("Content"):WaitForChild("Frame1"):WaitForChild("ViewportFrame")

I’ve come to accept that this is an OK practice since there is no other post that is better than this method, but I feel like it could be better. What do you recommend that I should do instead?

1 Like

Hi!

The best practice is to wait for the important components to have spawned in.

In your sample above, you forgot to make a variable for content. In this case you will have to make a variable that waits for content to be present.

Also for the viewport variable you have to use frame1:WaitForChild(“ViewportFrame”)

Edit:

So this is the best practice in your case.

local gui = script.Parent
local frame = gui:WaitForChild("Frame")
local content = frame:WaitForChild("Content")
local frame1 = content:WaitForChild("Frame1")
local frame2 = content:WaitForChild("Frame2")
local viewportFrame = frame1:WaitForChild("ViewportFrame")

I’m aware that there is a variable missing, and that frame1 could be used for viewportframe, but the question was: Is WaitForChild() a bad practice? Because it seems to be repetitive in this scenario / code, and I’m wondering if there is a non-repetitive method for this.

I’ve posted the right approach. As I stated above, wait for the important components to be present.

Edit: If you never use frame2, remove that variable.

So essentially, you’re stating that my method was indeed the right approach, and essentially, you’re pointing out things that weren’t pertaining to the question. So, what if it was correct? I am still seeking a better way to write this.

What I’m trying to ask is:

Instead of using WaitForChild() for every object in the Gui, what is a more optimal way to get the objects without using WaitForChild() on every single variable?

I’m stating that the script you presented was not the correct way of doing it, due to a missing variable, and you didn’t use your frame1 variable for viewportFrame.

There is not a more optimal way of making sure a component is present.
If you want to be sure that a component is present, you use WaitForChild.
If you want to check if a component is present, you use FindFirst…
If you only use a variable in your code once, you can (if you wish so) skip making the variable

local frame = gui:WaitForChild("Frame")
local frame1 = frame:WaitForChild("Content"):WaitForChild("Frame1")
local viewportFrame = frame1:WaitForChild("ViewportFrame")
local viewportFrame = gui:WaitForChild("Frame"):WaitForChild("Frame1"):WaitForChild("ViewportFrame")

But the last section comes down to what you prefer.

I understand what you’re trying to say… But again, this is an example of the method WaitForChild() being used.

Whether the variable is missing or not, it is still using WaitForChild() for this, and you’re just adding another variable to the code. This doesn’t make it the most optimal way because you’re writing another WaitForChild(), does that make sense?

So essentially, you’re just pointing out obvious mistakes that can be fixed, but that does not answer the question because the question is about what is the optimal way to wait for the objects without using WaitForChild().

There is no such thing as a more optimal way of waiting for a component. You use WaitForChild. :slight_smile:

Sometimes we’ll have to sit back, and stop finding ways to opimize something, when there is no optimization to be made. I’ve done it a lot myself in the past.

1 Like

The only optimization you could do, is setting up your GUI in a better fashion. Imagine that each time you put a UI object into another UI object, you create a new table. So in a large dictionary, it can be a good thing to make a new child, instead of have all the objects inside the same child.

The green marked sample is the more effecient way of finding “Cyan Component”, even though it looks like it’s more complicated.

1 Like

Unfortunately, there is a better way to wait for objects.

3 Likes

Could you please point it out to me, so I don’t have to read all the replies in that thread? :slight_smile:

If you read the solution to the post, you will see the solution.

Sometimes we’ll have to read carefully and do some more research, and stop assuming that there is nothing to improve, when anything can be improved. I’ve done it a lot myself in the past.

3 Likes

Interesting, but I think we’ve talked past each other.

I was trying to explain to you the fastest way to make sure a object is a thing. I can see that the solution in the thread stated something I wasn’t aware of which is great.

What I tried to explain to you, is that the fastest way to make sure that “Cyan” component is present (look at my sample above), is to divide all our components into sections, instead of having 1 large section with all the components.

I found this video on youtube, which explains a similar case but with sorting. We can use this principal to even faster find a component.

If we in the red marked area, tries to find Cyan. Then we in our script do:

Parent.Cyan

If we in the green marked area, tries to find Cyan. Then we in our script do:

Parent.Child.Cyan

But red area goes through up to 6 components before finding the right one, where as green only goes through up to 4. At least that is the practice for FindFirst…

Edit: But as you mentioned, you only wanted to know if using :WaitForChild() for all components was neccessary, which in the thread you found, you’ve already figured out wasn’t the case. Which is good news! :slight_smile:

:WaitForChild() is perfectly fine practice if you know it will appear quickly, but not quick enough for a regular reference (gui.Frame)
If you know it will be yielding on that line for a very long time without a set timeout (for example, waiting an entire round) then it is bad practice, and there are far better alternatives to it.

Also, side note, you don’t need/shouldn’t have every single instance under a :WaitForChild(). If you know that Content will always have Frame1 and Frame2 then you can just have it wait for Content and directly point to Frame1 and Frame2 underneath.

(btw viewportFrame can easily be changed to be local viewportFrame = frame1:WaitForChild("ViewportFrame") since you already made a variable pointing to Frame1)

Personally I wasn’t aware of this before Dayo pointed it out through a thread he found