TL;DR
Use ipairs loop:
for _, KillBrick in ipairs(KillBricks:GetChildren()) do
KillBrick.Touched:Connect(respawn)
end
Explanation
You need to use a thing called generators or iterators or just loops, a brief description of iterators is "they will repeat code block while specified function does not return nil", in your case you will use it to repeat a code while next child exists.
Generators are created the same as normal functions:
local function generate()
end
For generators there is a built-in syntax that looks like this:
for ... in generator_function do
end
Where ... stands for parameters returned by the generator, the code between do and end can be called an iteration, while generator is running it will repeat this code forever in a loop.
Generators should return a value, let's return 5 as an example:
local function generate()
return 5
end
for number in generate do
print(number)
end
This will print number 5 repeatedly until it breaks, for me it printed the number 4996 times. They way this worked is that it called the generate function, the function returned 5 so number variable held value of 5, it was not nil so the iteration code was ran which was just print(number), after the iteration finished, it repeated the same action, it called generate again, the function returned 5, number held value 5 and the iteration code began running, this is an infinite loop.
This was bad way of making a generator, let's make a generator that will loop over all children in the KillBricks folder, using Instance.GetChildren you can get list of them. To create a generator for this task, you need to know at which position in the list you are, return a child at that position, run the iteration function and increment the position, repeat that until position is out of the children list bounds (means all children were looped through). A good way to create this is to make function which returns generator, this will let you create local variables inside the generator:
local function iterateChildren(instance)
local children = instance:GetChildren()
local index = 0
return function()
index += 1
return children[index]
end
end
local KillBricks = game.Workspace.KillBricks
for KillBrick in iterateChildren(KillBricks) do
print(KillBrick)
KillBrick.Touched:Connect(respawn)
end
Cool generator, but since this is used very often, Roblox has a built-in generator that will do this thing for you, it's called pairs and ipairs, first one returns generator that loops through all elements in table and returns current position and the value at that position for the iteration, position can also be a key, example:
local t = {
a = 5,
b = 100,
c = "Hello",
d = 2000,
[1] = 200,
[2] = 300,
[4] = 30000
}
for key, value in pairs(t) do
print(key, value)
end
You may see that its order is randomized, this is not true for ipairs which goes strictly by order and only works for positions, this makes it faster:
local t = {
a = 10,
20,
30,
[4] = 600
}
for index, value in ipairs(t) do
print(index, value)
end
a was straight ignored and it stopped at position 2 since it could not find position 3. Since :GetChildren returns table in ordered form, ipairs is the best fit in your case.
Sources
ipairs and pairs
some post about generators
roblox tutorial about loops that also includes pairs and ipairs
6 comments
Thank you very much it worked. I know how the for loop works now. But i still have some questions. For example. Will it work if i just wrote " for KillBrick in KillBricks do "? (notice i didnt use ipairs()). If it doens't, why doesn't it?
it doesn't because generators need a function after the
in, Lua was built to be very simple and small language, it could predict that you want to iterate over KillBricks folder like Python does for example, but this would add more lines of code to the language which was not what Lua owners wanted.Oh, okay. So if Im getting this right, how the "cool generator" one that doesn't use ipairs works is. 1. The for loop calls iterate children. The iterate children gets the children of killbricks, assign them to an index, and the call the function again? (line 19). And then adds the index by 1 then it loops like that?
iterateChildren gets table of children and creates a variable index, then it returns function and the for loop uses this returned function as a generator, it calls this function, the function increments the index and returns child at that index -> KillBrick variable assigned to it, after "do" "end" finishes, it calls the returned function again without calling the "iterateChildren"
https://gist.github.com/kirdaaa/119310176d2e708bcbb387e547db506d
Very good, never thought you can optimize your code like that, just putting thousands of kill briks into a single folder and use a single 3 lines code, amazing