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')
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
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
isn’t Instance | nil the same exact thing as Instance??
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
yeah, this was my question exactly. if you ever have a scenario like this, that isn’t the engines fault, that’s purely the user who is at fault.
the only ever time where you would need to have access to a specific instance that shares the same name with other instances under the same instance, would be if something interacts with said instance (lets say its named “button” under the “buttons” folder) and you need to change its parameters.
however, what you would do in this case is loop through each child and give it a mb1 click event connection (just an example if you are using a click detector) and run the logic there… this will give you access to the button instance (since you are looping through each one) so there shouldn’t be a problem
if each button does a different thing, then name the buttons after what they do!
Guys, I had a crazy idea. Just don’t add dots to actual object names. It’s time-consuming to get the object in scripts and just confusing in general.
This reads as looking for engine compensation for poor organization. In the example given, you’re looking to reflect state behavior through instance existence and then citing the fact that checking in the way leads to bloated code. That is correct, it does. The better question is why are you reflecting your game’s states this way when there are lots of cleaner ways (e.g., modules in the most general sense or state management libraries) to go about it?
local function deepFFC(parent,completeName)
for _,name in string.split(completeName,".") do
parent = parent:FindFirstChild(name)
if not parent then return end
end
return parent
end
-- Example
local part = deepFFC(workspace,"Folder.Model.Part")