Deep WaitForChild and FindFirstChild functions

Chaining WaitForChild and FindFirstChild can generate lots of junk variables and redundant logic.

Consider:

local remoteFolderRbx = ReplicatedStorage:FindFirstChild('Remote')
local avatarEditingRemoteFolderRbx = if remoteFolderRbx then remoteFolderRbx:FindFirstChild('AvatarEditing') else nil
local resnapRemoteRbx = if avatarEditingRemoteFolderRbx then avatarEditingRemoteFolderRbx:FindFirstChild('Resnap') else nil

if resnapRemoteRbx then
	resnapRemoteRbx:FireClient(player)
end

The variables remoteFolderRbx and avatarEditingRemoteFolderRbx only exist so that I can introduce a branch that tells the operation whether to continue or not. It would be more concise and performant to use a single function that handles this all-or-nothing operation for me.

local resnapRemoteRbx = ReplicatedStorage:Find('Remote.AvatarEditing.Resnap')

Keeps the code cleaner and performs better.

3 Likes

If I’m not mistaken, you can literally use FirstFirstChild’s recursive boolean to iterate through all descendants and find it

link

. Also, why not just do local resnapRemoteRbx = ReplicatedStorage.Remote.AvatarEditing.Resnap ?

Well going off you’ve got fireclient server doesn’t need to wait for things to load, plus you can do a recursive search with findfirstchild if you add true to the second parameter.

^ Using the second parameter for FindFirstChild is not always an option if there can be multiple descendants of the same name. OP’s function suggestion makes a lot more sense imo.

You can already do something similar. Here is my preferred version:

-- Usage:
getInstance(game.ReplicatedStorage, "Remote", "AvatarEditing", "Resnap")

-- If the target instance is not found, nil is returned as the first value, and the last found child as the second value
function getInstance(parent: Instance?, ...: string): (Instance | nil, Instance?)
	if parent then
		local nestedAmount = select("#", ...)

		local instance = parent

		for index = 1, nestedAmount do
			local name = select(index, ...)
			local currentChild = instance:FindFirstChild(name)

			if not currentChild then
				return nil, instance
			end

			instance = currentChild
		end

		return instance
	end

	return nil, nil
end

But having a built in function would be nice.

I do unfortunately see a potential issue with needing to escape instance-names which include dots within either their name or one of their ancestors’ names, though. As a bit of reference, the functions GetFullName and debug.info("s") are a bit of a nightmare to use because they don’t support any escape-characters and hence it can be ambiguous as to what instance they are referring to; just in-case the actual referenced instance actually has a dot anywhere in its name or one of its ancestors’ names. For example, with the following simplified hierarchy; if we were to search for Workspace.Model.Test.Part:

Workspace
├── Model
│   └── Test.Part
│   └── Test

It’s ambigious as to whether we are searching for “Test.Part” under “Model” which exists; or “Part” under “Test” which doesn’t exist and hence should return nil. Ideally, we’d like to have way of referencing both so we’d either need to have an escape character in-order to clear up any ambiguity without making certain instances inaccessible through the method; or alternatively a seperate way to reference the path which doesn’t see this ambiguity limitation.

so… why does the 2nd argument of FindFirstChild not work for you in this scenario?

Why would you need to find a specific object that has the same name as multiple other objects and why would you have a findable object have the same names as other objects in the first place :confused:

isn’t Instance | nil the same exact thing as Instance??