Is there a performance / functionality difference between using
:FindFirstChild(“name”,true) vs :FindFirstDescendant(“name”)?
FindFirstChild initially finds the child stated in the parentheses. If it is not found, it returns nil. A descendant is all the children within the specified parent. Judging by that, FindFirstDescendant returns the first descendant found with the given name.
Well no, if you didnt notice you could also use FindFirstChild with the recursive option (“name”,true) and that would ultimately do the exact same thing FindFirstDescendant does
My question is, is there a performance difference or certain instances where you could use FindFirstChild but not FindFirstDescendant or the other way around
Very good point. However, you should know the GetDescendants()
function, which returns all the descendants from the specified parent. From there, FindFirstDescendant will look through ALL the children of the parent until the object is found. FindFirstChild on the other hand has to have the parent of the object to find it. Example:
local Parent = script.Parent
Parent:FindFirstDescendant("TextBox") --That would check the parent's children until "TextBox" is found.
However, if we are using FindFirstChild, you need to add the parent of the child’s name, like this:
local Parent = script.Parent
local Frame = Parent.Frame
Frame:FindFirstChild("TextBox")
In that instance, it needs the initial parent of the child you are trying to find before you can find it. Otherwise, it will return nil. Now, I never use descendants, but from my knowledge, this is correct.
You aren’t really getting my point, which is understandable because for some reason not many people know about that functionality of FindFirstChild…
Instead of doing
local Parent = script.Parent
local Frame = Parent.Frame
Frame:FindFirstChild("TextBox")
you could do
script.Parent:FindFirstChild("TextBox",true)
the true is the recursive property, it’ll also go through all of the descendants until it finds “TextBox”
so you don’t need the initial parent of the object you’re looking for
Both of them could work similarly then. It would be up to you if you’d like to use one vs the other!
I guess you can do benchmark yourself, but FindFirstDescendant imo should be faster because it is strictly for finding descendants and not some second argument of different use case function .
Right, but my question is what’s the difference between them?
is there any reason to use FindFirstDescendant over FindFirstChild?
for example I know roblox does (source is a previous forum post here
function pairs(t)
return next, t, nil
end
for i,v in pairs (t) do
which is basically just
for i,v in next , t do
which is exactly the same thing but made into its own thing for nicer looking code
is FindFirstDescendant the same? is it just
function FindFirstDescendant(name)
return FindFirstChild(name,true)
end
Instance:FindFirstDescendant(...)
is just an alias for Instance:FindFirstChild(..., true)
, so no.
Would the recursive method for FindFirstChild(object, true) be a performance difference? If not then I think you have your answer.
If I was looking for a descendant, I’d use :FindFirstDescendant
, because :FindFirstChild(..., true)
would be coded internally differently to account for the second argument, but I still assume they run the same code to find the first descendant, the difference would be that FindFirstChild()
branches when the second argument is true. So if you are concerned, stick with FindFirstDescendant
, but ultimately there should be no real measurable difference.
Well actually, FindFirstDescendant is not enabled yet, sooooo, don’t even bother.
If you call InstanceA:FindFirstChild("InstanceB", true)
like this then the search for the instance named “InstanceB” becomes recursive and the children of InstanceA are searched and their children are then searched essentially giving FindFirstChild() the same behavior as FindFirstDescendant().
https://developer.roblox.com/en-us/api-reference/function/Instance/FindFirstChild
If the optional recursive argument is true, this function searches all descendants rather than only the immediate children of the instance.
There isn’t really any reason to do so, it just is your personal preference!
I would argue that roblox engineers made the recursive option to be as smooth as possible in some way.
Otherwise they would state in their api to write ur own functions
The Instance:FindFirstDescendant(string) function performs a Breadth First Search (BFS), while the Instance:FindFirstChild(string, true) function performs a non-standard search algorithm, but similar to Depth First Search (DFS). The reason that the function is different from DFS is because it first searches the children of the current instance before recursing into the child instances.
The function can be enabled by changing the Fast Flag named “EnableFindFirstDescendant2” to true.
For anyone who needs an example to understand the difference between these two functions,
here is an instance hierarchy:
[BFS] Instance:FindFirstDescendant(string)
[DFS-like] Instance:FindFirstChild(string, true)
It’s pretty clear why Roblox decided to create a new function instead of modifying the old one.
But I’m confused about why Roblox hasn’t enabled this function after being included in client builds since 2021-05-03 according to a client api tracker. If I had to make a guess, it would be that BFS and DFS have bad time complexity for Roblox’s common hierarchy, so they rather make you implement your own search algorithm if needed.
Anyway, I hope this clears up the difference between the functions for you and anyone else who is wondering the same.
Hey!
Here’s a simple explaination of the difference between :FindFirstChild()
and :FindFirstDescendant()
:
Let’s say we have a variable ‘Part’ which is a part.
local Part = workspace.Part
Children are objects DIRECTLY parented to a part. This means: The ‘Parent’ property of an object must be the part for it to be considered as a child.
Descendants are children of objects, that are children of the part. Descendants can also be the children of the part itself. So let’s say you have this structure:
Workspace → Part → SurfaceGui → Frame
The SurfaceGui is a child of the part.
The Frame is not a child of the part.
Both, the SurfaceGui and Frame are descendants of the part.
The :FindFirstChild("name")
method returns the child itself when it does exist. Otherwise nil.
The :FindFirstDescendant("name")
method works in a similar way but returns the descendant if it exists - otherwise nil.
So if we take a look at the simple structure we made above we can can see:
workspace.Part:FindFirstChild('SurfaceGui') --// SurfaceGui
workspace.Part:FindFirstChild('Frame') --// nil
workspace.Part:FindFirstChild('RandomObject') --// nil
workspace.Part:FindFirstDescendant('SurfaceGui') --// SurfaceGui
workspace.Part:FindFirstDescendant('Frame') --// Frame
workspace.Part:FindFirstDescendant('SurfaceGui') --// nil
Let me know if you have any questions!