:GetChildren() returns an array, not a dictionary, and pairs() with ipairs() are meant to be used with dictionaries
here’s an example codeblock:
-- loop through all the enemies
for _, enemy in ipairs(enemies) do -- why use ipairs when it's an array?
-- get required parts of the enemy
local enemyRootPart:BasePart = enemy:FindFirstChild("HumanoidRootPart")
local enemyHumanoid: Humanoid = enemy:FindFirstChild("Humanoid")
-- if the enemy is unable to attack in any form
-- like it's dead or something, skip the iteration
if not CanEnemyBeUsed(enemy) then continue end
-- get stats of the enemy
local enemyMaxHealth = enemyStats[enemy.Name].health
local enemySiphonOnKill = enemyStats[enemy.Name].siphon
local enemyDeathEvent = enemyStats[enemy.Name].deathEvent
local enemyBehavior = enemyStats[enemy.Name].behavior
local enemyAttackTimes = GetAttackTimes(enemy)
end
The Lua(u) table is a hybrid data structure. It’s internally comprised of an array component and a hash-map (dictionary) component. pairs and ipairs are iterator factories designed to produce specialized iterators for the traversal of this data structure. They do not do the same thing.
An ipairs iterator will traverse by ascending indices, which typically results in the elements of the array component from left → right. The iterator will cease function upon discovering a nil element
pairs uses the next function, which is designed to cover both the array and dictionary components. Dictionaries cannot naturally preserve insertion order, so a pairs iterator traverses in no defined order. The iterator will cease iteration upon reaching the end of the table
TL;DR: ipairs is optimized for traversal of the array component, while pairs is designed to cover the entire table.
With the introduction of generalized iteration, both factories are no longer required
Originally it was necessary to loop through a list of items, now it isn’t. Ipairs runs numerically for lists, so it can be beneficial at times. It doesn’t work for objects with non-numeric key value pairs, and it also stops at the first nil value(in standard lua). I would recommend playing around in Roblox so you fully understand the differences.