Which is reliable when waiting for an instance, loop function or WaitForChild?

Hello, I’ve been having trouble with instances replicating way too late and my localscripts getting nil indexes on those instances children/descendants.

Should WaitForChild be used as opposed to this function?

-- I'm using this function
function ClientLibrary.GetModel(player)
	local Model = workspace.Models:FindFirstChild(player.Name)
	
	RunService.Heartbeat:Wait()
	if not Model then Model = ClientLibrary.GetModel(player) end
	
	return Model
end

-- Same as this
function ClientLibrary.GetModel(player)
   local Model = workspace.Models:FindFirstChild(player.Name)
   while not Model do
      Model = workspace.Models:FindFirstChild(player.Name)
      RunService.Heartbeat:Wait()
   end
   return Model
end

Edit: I know that my question might seem obvious to some, and I could’ve just experimented to check before deleting this. But I left it just in case somebody out there looks for this problem. Since I couldn’t find a topic similar to it.

The first one would cause your function to call itself, many times, causing the script to probably reach the exhaust limit or just halting the thread and being just overall more expensive than it has to be, the second one should be used.

As for whether you’re going to use :WaitForChild or your function, it doesn’t really matter as they do essentially the same thing; halting the thread until the model is found. The only reason you’d want to use :WaitForChild is because of the infinite yield warning :WaitForChild offers as well as the timeout argument.

So all in all, it doesn’t really matter whether you want to use your custom function or if you want to use :WaitForChild, but you would want to use the second function over the first one.

1 Like

But does WaitForChild also yield until all of its descendants are completely replicated?

No, it only yields until it finds a child specified as the argument.

If you want to wait until all of the descendants are replicated, maybe you could add a BoolValue and set it to true once the script has finished moving all of the descendants over.

Then on your other script, you could do something like

local descendantsComplete = model:WaitForChild('DescendantsComplete')
while not descendantsComplete.Value do
    runService.Heartbeat:Wait()
end

Just wondering…
does

#Model:GetDescendants()

also count children that haven’t fully replicated?

repeat
   RunService.Heartbeat:Wait()
until #Model:GetDescendants() == 300
1 Like

:GetDescendants() only returns the descendants that existed at the time of it being called. So no, it shouldn’t include any instances that haven’t been replicated yet.

ex.

localscript:

local myModel = workspace.Model

wait(2)

print(#myModel:GetDescendants()) -- would print ~20 depending on ping and whatnot

Server:

for i = 1,1000 do
    local part = Instance.new('Part')
    part.Parent = workspace.Model
    wait(0.1)
end
1 Like