In this question, I will be focusing mainly on :FindFirstChild() and :WaitForChild(). Often I am confused and uncertain as to whether or not I should use one, or neither, of the listed methods. Because :FindFirstChild() returns nil when the object is not found, I am sure that I should not use it like this:
local box = game.Workspace:FindFirstChild("Model").box
Because :FindFirstChild() returns nil, the variable definition will error. If I am doing it that way, why not just do:
local box = game.Workspace.Model.box
I can see using :FindFirstChild() if the name has spaces, but I could just do something like this:
local box = game.Workspace["Box Model"].box
If I want to use :FindFirstChild() without it erroring, I end up needing to do checks all along the way like this:
local boxModel = game.Workspace:FindFirstChild("Box Model")
if boxModel then
local boxHolder = boxModel:FindFirstChild("Box Holder")
if boxHolder then
box = boxHolder:FindFirstChild("box")
if box then
-- code
end
end
end
That method just seems extremely inefficient. Another thing I have done to be careful is this:
local players = game:GetService("Players")
players.PlayerRemoving:Connect(function(player)
local canSave = player;FindFirstChild("CanSave")
if canSave and canSave.Value then -- canSave is a BoolValue
--code
end
end
There must be a better or more efficient and intelligent way to go about using :FindFirstChild().
I have been told :WaitForChild() is for the client when waiting for things that have not spawned in yet. This makes sense, until I talked to someone on the discord (this is the code that was in the discussion):
local text = script.Parent
local players = game:GetService("Players")
local player = players.LocalPlayer
local contentProvider = game:GetService("ContentProvider")
local loaded = player:WaitForChild("Loaded")
local connection
while contentProvider.RequestQueueSize > 0 and not loaded.Value do
for i = 1, 3 do
text.Text = "Loading"..string.rep(".",i)
wait(.5)
end
end
local backpackDisplay = player.PlayerGui.StatsGui.Backpack.Display
require(backpackDisplay)
text.Parent.Visible = false
The backpackDisplay was not working correctly and I was uncertain why because the loop should have waited till everything had loaded in. After asking on the ScriptingHelpers discord I was informed that RequestQueueSize did not count GUI stuff, but only assets. In order to fix this the person recommended using :WaitForChild, which made sense. I then became confused as to where I should place the :WaitForChild. I tried doing this and it worked:
local text = script.Parent
local players = game:GetService("Players")
local player = players.LocalPlayer
local contentProvider = game:GetService("ContentProvider")
local loaded = player:WaitForChild("Loaded")
local connection
while contentProvider.RequestQueueSize > 0 and not loaded.Value do
for i = 1, 3 do
text.Text = "Loading"..string.rep(".",i)
wait(.5)
end
end
local backpackDisplay = player.PlayerGui:WaitForChild("StatsGui").Backpack.Display
require(backpackDisplay)
text.Parent.Visible = false
I went back and asked the guy who answered who answered my question originally and he said that was all that was needed. Why did I not need to do:
local backpackDisplay = player.PlayerGui:WaitForChild("StatsGui"):WaitForChild("Backpack"):WaitForChild("Display")
or, as one of the options I listed with the :WaitForChild(), why not do this:
local statsGui = player.PlayerGui:WaitForChild("StatsGui")
if statsGui then
local backpack = statsGui:WaitForChild("Backpack")
if backpack then
local display = backpack:WaitForChild("Display")
if display then
require(display)
end
end
end
All of these questions berate me whenever I am writing scripts involving objects, which as you may guess, is pretty much every time I script in Roblox Studio. Any help would be much appreciated. Thanks!

4 comments
there should be more questions like this :/
^ LOL I AGREE
Ew, nested conditionals. The 'and' operator and 'or' operators exist.
Yes, but those don't work in the situation that I pointed out. Also, I used and in my canSave example.