When to use dot operator, when to use FindFirstChild()?

This confused me a lot! Can you explain when is the best time to use the dot operator or FindFirstChild()?
Example:

local humanoid = character:FindFirstChild("Humanoid")
--or
local humanoid = character.Humanoid

Which one is better?

3 Likes

Dot operator is faster but will error if the referenced instance does not exist (or hasn’t yet loaded), whereas FindFirstChild() will instead return nil if the instance being referenced either doesn’t exist or hasn’t yet loaded. WaitForChild() will yield (suspend) the current thread’s execution until the referenced instance has loaded (if it exists) otherwise an infinite yield warning will occur.

The dot operator is required for properties of instances as those are properties and not children/descendants, I’d recommend using the dot operator in all circumstances where you know whether or not the instance currently exists/has loaded and then opt to use FindFirstChild() whenever this information isn’t known/isn’t guaranteed.

11 Likes

So, if I have a Part in the workspace, I can use the dot right?
workspace.Part

3 Likes

Yes, that will work providing the part has loaded from the perspective of the script it is being referenced from.

2 Likes

And another example, the player’s character does not exist in the workspace until I start the game. If I wanna get the character’s humanoid, I should do like this right:

local character = workspace:WaitForChild("FSXplay") --FSXplay is the name of my character
local humanoid = character:FindFirstChild("Humanoid")

Or can I use the dot to get the humanoid?

local character = workspace:WaitForChild("FSXplay")
local humanoid = character.Humanoid
2 Likes

Yes and no. FindFirstChild is ~20% slower than the dot operator. (even longer if called with recursion). If your code is heavily performance dependant, you will see a greater benefit out of alternative approaches. Large games need those kinds of optimizations.

That said, most small projects won’t experience the difference with any kind of visual impact.

It’s actually required because you’re indexing information from a userdata valuetype, just as you would index information out of any table.

print(type(workspace.Part)) -- userdata
print(typeof(workspace.Part["Color"])) -- Color3

OP, the only question you need to be asking yourself when deciding between the two is whether or not it makes sense to use. A common malpractice of FindFirstChild is only assessing its result once instead of saving it for later use. You will gain a better understanding of this with more practice and knowledge of Roblox’s engine.

There are very few reasons that you would be manually indexing any normal character controlled Humanoid. You can proceed with Player.CharacterAdded as you see fit instead.

You should see extended usage of FindFirstChild on the client’s end (because instances take time to replicate unless otherwise given NetworkOwnership) when you’re working with game content streaming excessively.

2 Likes

No, I think you should WaitForChild humanoid too because just because the character was made it doesn’t mean the humanoid, character parts, etc were loaded in yet.

Use “.” by default most of the time, if the child fails to be found resulting in an error then that would indicate that the child hasn’t yet loaded and you should use WaitForChild() instead, FindFirstChild() is useful in conditional statements as it can be used to check the existence of something without an error occuring if that thing doesn’t exist.

4 Likes

But if I do that, so when I can use FindFirstChild()?

2 Likes

Generally they are interchangeable I think. I usually use . but only use it if you’re sure that the Instance is there. Good place to use .: Getting a part from workspace
Bad place to use .: getting character and character humanoid

2 Likes

This is true, but as previously stated, one of the biggest pitfalls of learning scripters using FindFirstChild is running on an individual conditional statement that could otherwise be assessed without it. The information returned by FindFirstChild should be used across multiple statements or result in a thread yield. There’s no reason to consistently assess with FindFirstChild, which is benchmarked as slower, if you’re only going to use it once.

3 Likes

So after reading your replies, I have an idea:

  • If the object that I’m looking for has been added into the parent (and I can see it under its parent in the Explorer window), I can use the dot.
  • If the object that I’m looking for hasn’t been added into the parent yet (and I don’t see that object under its parent in the explorer window), I have to use WaitForChild().
  • After getting the object that I’m looking for by using WaitForChild(),
local character = workspace:WaitForChild("FSXplay") --FSXplay is the name of the character

then I can get the object’s child/descendant by using the FindFirst method.

local character = workspace:WaitForChild("FSXplay") --FSXplay is the name of the character

local humanoid = character:FindFirstChild("Humanoid")

Simplified:

  • If the object that I’m looking for can be seen under its parent in the Explorer window before I start the game, I can use the dot.
  • If the object that I’m looking for can’t be seen under its parent in the Explorer window until I start the game, I should use WaitForChild and FindFirst methods.

Is that right?

3 Likes

If you’re expecting it to not exist (like if a key is inserting to the door), use if : FindFirstChild, if you’re expecting it to be there( like mine an object with the default pickaxe), it’s still recommend to use FindFirstChild, but you can also use the dot operator

2 Likes

Alright! Now I’ve understood this, thanks for your replies!

1 Like