Common need: Find the humanoid of a character immediately when it becomes available after spawning.
Usual solution: WaitForChild.
humanoid = character:WaitForChild'Humanoid'
Why this is bad: Your code breaks if the humanoid isn’t named Humanoid, or if there’s another member of the character that happens to be named Humanoid. It’s ugly to make assumptions about name.
We decided against adding this, I’ll explain why.
Here were some of the obvious use cases:
Waiting for PlayerScripts to replicate
Waiting for Humanoids to replicate
Waiting for PlayerGui to replicate
You can see a theme where scripts are trying to use objects before they’re replicated–there are no guarantees that critical things will exist by the time scripts run.
There’s two ways address that:
Make an engine-level feature to work around the lack of guarantees; add WaitForChildOfClass
Get to the root of the problem and add those guarantees
Better to patch the boat than waste time bailing water, so we’re opting for the latter. This means more predictability and fewer edge cases in the long term.
Short term, you only need a few lines of code:
local function WaitForChildOfClass(parent, class)
local child = parent:FindFirstChildOfClass(class)
while not child or child.ClassName ~= class do
child = parent.ChildAdded:Wait()
end
return child
end
In case anyone wants a version that works similar to the Roblox one with a single warning and an optional timeOut
function WaitForChildOfClass(parent,className,timeOut)
local waitTime = 0
local warned = false
repeat
local obj = parent:FindFirstChildOfClass(className)
if obj then
return obj
else
waitTime = waitTime + wait()
if timeOut then
if waitTime > timeOut then return nil end
elseif not warned then
if waitTime > 5 then
warn("Infinite yield possible waiting on",parent:GetFullName() .. ":FindFirstChildOfClass(\"".. className .. "\")")
warned = true
end
end
end
until false
end