Hi.
Intro I'm making multiple parts that will kill you when touched. It works. But it doesn't look good when I have a lot of those parts and each of them contains a script that acts exactly the same. So I moved all of them inside a folder and left only 1 script to act for them all.
Problem
I don't know how to let the script know if any of those parts were touched. Here is the script that I have if it's any help at all.
local rs = game:GetService("ReplicatedStorage") local DeathScreen = rs.DeathScreen local Players = game:GetService("Players") local KillBricks = game.Workspace:FindFirstChild("KillBricks") local function respawn(hit) if hit and hit.Parent and hit.Parent:FindFirstChild("Humanoid") then local player = Players:GetPlayerFromCharacter(hit.Parent) DeathScreen:FireClient(player) hit.Parent.HumanoidRootPart.Anchored = true wait(.1) hit.Parent.HumanoidRootPart.CFrame = player.PlayerData.Checkpoint.Value + Vector3.new(0, 4, 0) wait(.3) hit.Parent.HumanoidRootPart.Anchored = false end end KillBricks.Touched:Connect(respawn) --I want it when one of the bricks inside KillBricks folder touch this event triggers
Use ipairs loop:
--KillBricks.Touched:Connect(respawn) --I want it when one of the bricks inside KillBricks folder touch this event triggers for _, KillBrick in ipairs(KillBricks:GetChildren()) do KillBrick.Touched:Connect(respawn) end
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 -- some code 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) -- list of all the children of the instance (all the killbricks for your case) local children = instance:GetChildren() -- current position of the list, every element in list -- has its own position, in this case all the children -- in the list have ordered position so we can -- increment the position to get the next child from -- the list -- first position is always 1, the reason why we start at -- 0 is because later we increment the position by 1 -- and we need to increment it before we call "return" local index = 0 -- this function is the actual generator that will be repeated -- every iteration this function will increase position to -- get the next child and return a value at that position -- from the children list, then the "do" "end" code will run -- where the parameter will be the next child return function() index += 1 return children[index] end end local KillBricks = game.Workspace.KillBricks for KillBrick in iterateChildren(KillBricks) do print(KillBrick) -- :Connect the function for currently iterated brick 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, -- key a b = 100, -- key b c = "Hello", -- key c d = 2000, -- key d [1] = 200, -- position 1 [2] = 300, -- position 2 [4] = 30000 -- position 4 } for key, value in pairs(t) do print(key, value) end --> a 5 --> 2 300 --> c "Hello" --> b 100 --> d 2000 --> 4 30000 --> 1 200
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, -- position 1 30, -- position 2 [4] = 600 -- position 4, notice how i skipped position 3 } for index, value in ipairs(t) do print(index, value) end --> 1 20 --> 2 30
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.
roblox tutorial about loops that also includes pairs and ipairs