How do I make one touched script for multiple blocks?

I’m working on a spleef Minigame, the problem is that there is one script for each brick, and I don’t find that is a good way to manage the blocks with the falling script. So I thought about make one script for every block, but I don’t know how to do it. Here is my current script:

local Block = script.Parent
local Debris = game:GetService("Debris")

Connection = Block.Touched:Connect(function(obj)
	if obj.Parent:FindFirstChild("Humanoid") then
		Block.Color = Color3.fromRGB(255,0,0)
		Block.Anchored = false
		Debris:AddItem(Block, 1)
		Connection:Disconnect()
	end
end)

I don’t know if I should use for i,v, and I don’t know how to use it, thanks for reading.

1 Like

You can use collection service
Try watching this video:

2 Likes

That would work if I clone something tagged with a tag?

put all the parts that will share the same script in a folder (or you can name them the same, but folder is more efficient) and just do folder:GetChildren() and iterate over the children, connecting each to a touched event.

--- example
for i = 1, folderChildren do
  folderChildren[i].Touched:Connect(function (obj)
      -- whatever touch needs to do
  end)
end

So this will work fine as long as the number of parts in the folder are constant and added from the start.

3 Likes

what about let the workspace find all the parts using workspace:GetChildren and to specify what the object is

local Debris = game:GetService('Debris')

for i,brick in ipairs(workspace:GetChildren()) do
if brick:IsA('Part') and brick.Name == 'BLOCKNAME' then
    brick.Touched:Connect(function(obj)
      if obj.Parent:FindFirstChild('Humanoid') then
        brick.Color = Color3.fromRGB(255,0,0)
		brick.Anchored = false
		Debris:AddItem(brick, 1)
		end
end)
end
end

That didn’t work, I guess, here is what I have made:

local Block = script.Parent
local Debris = game:GetService("Debris")
local Folder = script.Parent

for i = 1, Folder do
  Folder[i].Touched:Connect(function(obj)
      --etc.
  end)
end

@Da_RealHonestmam No, I need the script to only check the parts inside a model, how I would do that? Also, thanks for helping too.

you can’t iterate over an instance, you have to do :GetChilren() read what I said

local Block = script.Parent
local Debris = game:GetService("Debris")
local Folder = script.Parent

for _, part in pairs(Folder:GetChildren()) do
 part.Touched:Connect(yourFunc)
end

You have to iterate over the children of the folder

don’t iterate over :GetChildren() directly, assign a variable.
example (from what you gave):

local Block = script.Parent
local Debris = game:GetService("Debris")
local Folder = script.Parent -- No, don't put script in the folder, put it in serverscriptservice. Make it equal to something like game.Workspace.Folder
local Blocks = Folder:GetChildren()  -- You can just remove the Folder variable if you don't need it (like, if no parts will be added to it)  in which case you can do local Blocks = Folder path (i.e. game.Workspace.Folder or whatever):GetChildren() directly.
for i = 1, #Blocks do
 Blocks[i].Touched:Connect(yourFunc)
end

EDIT: If blocks are added to folder, then you also have to Connect to Folder.ChildAdded
ex (after the code above):

Folder.ChildAdded:Connect(function (c) 
c.Touched:Connect(yourFunc)
end)

Is using a for i = num, num do loop going to be more efficient than a for pairs loop that uses the same table of children?

Yes, numeric for loop is the most efficient, pairs the least, from what I’ve read. Though it doesn’t make a real world difference as I’ve read, I still prefer it.

Actually with all the luau optimisations pairs and ipairs are faster now.

ipairs is pretty much the standard when traversing arrays, so use it.

2 Likes

Can you verify? Because it’s a known fact by most experienced scripters that numerical is the most efficient (albeit negligibly for most cases). I don’t think is possible for ipairs or pairs to ever surpass numerical (but keep in mind, difference is neligible).

This is just blatantly wrong. There’s no such thing as a ‘standard’ when it comes to this, all three are viable.

I remember there was probably a devforum article on here that tested that out and that numeric is still fastest but that ipairs or pairs (I forgotten) was very close by like 0.001 second, so its virtually no difference but probably numeric is still fastest.

Numeric always will be the fastest (but remember, negligibly! I’m not here to invalidate pairs and ipairs, those are fine to use too in most circumstances with practically no drawback), and I think that’s partially tied to datatypes and native functions.

Not wrong, it wouldn’t be incorrect to iterate another way, but ipairs guarantees order, and the length operator is undefined on tables with holes. Heck personally I consider using table.pack(...) because of the n field

local t = table.pack(nil, nil, nil)
local t2 = { nil, nil, nil }
print("t.n =", t.n)
print("#t2 =", #t2)

I don’t think ipairs and pairs surpass a numeric for loop but either way ipairs and pairs are idiomatic. My DMs are open so feel free to send a message so we can continue on this

For something to be a standard, most people have to agree that one way is the right way. On the contrary, most people agree that differences are negligible therefore doesn’t really matter which way you do it.

You really sent me on a wild goose chase with the Faster Lua VM topic, I’ve spent the last hr reading it and testing. Running the person’s exact test who claimed it was faster, still produces results showing numeric is fastest. My own test also indicates numeric for loop is the fastest.

You’re spending time arguing about negligible speeds here. A numeric for loop does not make sense to be using here. It is idiomatically incorrect and it makes what you’re doing stupidly obscure as far as readability goes. Use ipairs when iterating over arrays. Numeric for loops are inappropriate in this situation and if you’re using them the same as ipairs, you aren’t getting the full benefits of a numeric for loop and its expressions.

Not to mention that you’re performing a table lookup every iteration which is already not a pleasant thing to be doing. Generic for loops have their variables localised to the current iteration. It’s unclear why you’d prefer constant lookups over n elements instead of a local variable. In idkhowtocode’s sample, what they did wasn’t wrong, it was just they used pairs over ipairs. You can and should iterate over GetChildren directly, its unclear what the problem is.

You mentioned at one point that “most experienced scripters say numerical is most efficient”. Where’s your citation? And even if that is the case - although efficiency is not at all a question here and its actually about performance - that doesn’t mean developers use numeric for loops. Saying something is the way it is doesn’t equate to using it as well. Several developers encourage the use of pairs and ipairs, situation dependent. Go on and ask who would use what given a table scenario. There’s no reason to take long winded methods and hamper readability or even functionality (which is possible if you use the wrong type or there are incorrect names or variables).

Viability doesn’t equate to standard either. ipairs is standard for iterating through arrays, pairs is for dictionaries. This is done by design of the language, not dogmatic principles that are specific to the Roblox platform or whatever.


On a separate note, if you’re interested about numbers for loops:

2 Likes

I got an error, that is printing Touched is not a valid member of Model, I don’t know what i have made wrong, here is the script:

local Debris = game:GetService("Debris")
local Touched = false
local Folder = script.Parent

for i, Block in ipairs(Folder:GetChildren()) do
	Block.Touched:Connect(function(obj)
	if not Touched  and obj.Parent:FindFirstChild("Humanoid") then
		Touched = true
		script.Parent.Color = Color3.fromRGB(255,0,0)
		script.Parent.Anchored = false
		Debris:AddItem(Block, 1)
		end
	end)
end

@viindicater
That didn’t work.

Check if Block is a BasePart before the Touched event.