Assuming you are searching for a particular object in an Instance, you may want to check the name. If said name varies based on scenario, you can use a function written by me to assist you.
local function WaitForChild(parent: Instance, ...): Instance
local t = { ... }
local l = t[#t]
local c
if typeof(l) == 'number' and l > 0 then
c = l
else
c = math.huge
end
local time = tick()
local n = {}
for i, v in pairs(t) do
if typeof(v) == 'string' then
table.insert(n, v)
end
end
for i, v in pairs(parent:GetChildren()) do
if table.find(n, v.Name) then
return v
end
end
local r
local connection; connection = parent.ChildAdded:Connect(function(child)
if table.find(n, child.Name) and typeof(r) ~= 'Instance' then
r = child
connection:Disconnect()
end
end)
local w
repeat
task.wait(0)
if tick() > time + 5 and typeof(parent) == 'Instance' and not w then
w = true
warn('Infinite yield possible on ' .. parent:GetFullName() .. ':WaitForChild(...)\n' .. debug.traceback())
end
until typeof(r) == 'Instance' or tick() > time + c
if typeof(connection) == 'RBXScriptConnection' then
connection:Disconnect()
end
return r
end
One example would be Humanoid.RootPart["Root Hip"], the name may otherwise be RootJoint, so you could use this function as such:
local RootJoint = WaitForChild(Humanoid.RootPart, "Root Hip", "RootJoint", 5)
-- Last argument means 5 seconds until yield is forced to complete, returning nil.
local function M_WaitForChild(parent: Instance, ...): Instance
local names = {...}
local object = nil
local thread = coroutine.running()
for _, v in names do
if object then
break
end
object = parent:FindFirstChild(v)
end
if object == nil then
local connection
connection = parent.ChildAdded:Connect(function(child)
if table.find(names, child.Name) and object == nil then
object = child
task.spawn(thread)
connection:Disconnect()
end
end)
coroutine.yield(thread)
end
return object
end
Improved, you’re just long polling as @twinqle said.
Im not sure where exactly do you mean by coroutine, but if it’s about the coroutine.yield, the purpose of that is to actually stop the thread that called the function. If you don’t and object is still nil, the ChildAdded event will fire without it returning the actual object because the function is already done, I hope i cleared this up. Edit: this logic also applies to SignalModules:Wait()
A better solution is: (Similar to the one of @ATrashScripter)
local function WaitForChildWithName(Object, ...)
local Names = {...}
for i, Name in Names do
local Item = Object:FindFirstChild(Name)
if Item then
return Item
end
end
----------------------------------------------------------------------
local Thread = coroutine.running()
local Connection; Connection = Object.ChildAdded:Connect(function(Item)
if table.find(Names, Item.Name) then
Connection:Disconnect()
task.spawn(Thread, Item)
end
end)
return coroutine.yield()
end
local function M_WaitForChild(parent, timeout, ...)
local names = {...}
timeout = timeout or 5 -- feel free to edit
local object = nil
for _, v in names do
object = parent:FindFirstChild(v)
if object then
return object
end
end
local thread = coroutine.running()
local connection
connection = parent.ChildAdded:Connect(function(child)
if table.find(names, child.Name) then
object = child
task.spawn(thread, child)
connection:Disconnect()
end
end)
task.delay(timeout, function()
if object == nil then
connection:Disconnect()
task.spawn(thread)
end
end)
return coroutine.yield()
end
task.delay(6, function()
local c = Instance.new("Part", workspace)
end)
local obj = M_WaitForChild(workspace, nil, "Part", "Whatever")
warn(obj) -- prints nil
Ok, I pretty much combined @focasds’s and my solutions (I didn’t know that you could send in other arguments in task.spawn when resuming thread) and I added a task.delay function which checks if the object is nil. If it is, it disconnects the ChildAdded function and resumes the current thread. You can check my example above.
Thank you so much. I’m not very familiar with working with the task scheduler. Learning more about this will definitely help with improving game performance!