I am using the Collection Service to make parts with a certain tag kill people. It works perfectly but when i create a new part and give it the tag touching the newly spawned in part does nothing, what am i doing wrong?
local CollectionService = game:GetService("CollectionService")
local KillBricks = CollectionService:GetTagged("KillBricks")
local Part = Instance.new("Part",game.Workspace)
Part.Name = "KillBrick"
CollectionService:AddTag(Part,"KillBricks")
CollectionService:GetInstanceAddedSignal("KillBricks"):Connect(function()
for i,KillBrick in pairs(KillBricks) do
KillBrick.Touched:Connect(function(hit)
local humanoid = hit.Parent:FindFirstChild("Humanoid")
if humanoid then
humanoid.Health = 0
end
end)
end
end)
You only get the list of your killbricks at the beginning of your script.
The table does not automatically update, you have to run GetTagged again when new parts are added.
This code runs once when the server starts meaning anything added during runtime won’t be check. You can use workspace.DescendantAdded to run the check on that newly added instance
For starters, it’s unnecessary to cache your parts. CollectionService passes a newly tagged object as an argument to your connected function, so you should treat each part independently. Right now your script is going to duplicate connections very badly.
local CollectionService = game:GetService("CollectionService")
local function onNewKillBrick(part)
if not part:IsA("BasePart") then return end -- Early out if not a part
-- A print just to show that it works
print("Registering a new kill brick")
part.Touched:Connect(function (hit)
-- Put your kill code here
end)
end
-- Doing it this way is important to prepare for Deferred SignalBehavior
-- eventually becoming the default for Roblox events.
CollectionService:GetInstanceAddedSignal("KillBrick"):Connect(onNewKillBrick)
-- Here we'll apply it to existing ones.
for _, killBrick in CollectionService:GetTagged("KillBrick") do
onNewKillBrick(killBrick)
end
-- And here, we can add a new one for testing. Remember to not use the
-- parent argument of Instance.new.
local part = Instance.new("Part")
part.Name = "KillBrick"
part.Parent = workspace
-- There are instance-level tagging methods you can use.
part:AddTag("KillBrick")
Your current code by design will only repeatedly connect to Touched for parts that exist before you establish the connection, though it does have another issue as well which is that you’re unnecessarily performing an iteration across existing tagged parts in your connection which you shouldn’t. Treat each new part independently.
Instead of using tags and CollectionService, you could put all the kill bricks into a folder and insert a script. Name it KillBrickHandler.
The hierarchy should look like this:
Insert this code into your script:
local folder = script.Parent
for _, part in pairs(folder:GetChildren()) do
if part:IsA("Part") then
part.Touched:Connect(function(otherPart)
local Character = otherPart.Parent
local Humanoid = Character:FindFirstChild("Humanoid")
if Humanoid then
Humanoid:TakeDamage(Humanoid.MaxHealth)
end
end)
end
end
You could try moving the per-killbrick logic (the Touched connection) to its own function (I’ll call it setup(part) here), looping through all of the killbricks found with :GetTagged() once and calling setup(part) on each of them, and then connecting the InstanceAddedSignal to setup
So:
local CollectionService = game:GetService("CollectionService")
-- Define a setup function to reduce code duplication
local function setupKillbrick(part)
part.Touched:Connect(function()
-- Your logic goes here
end)
end
-- Loop through all of the killbricks that already exist when the script loads and set them up
for _,part in CollectionService:GetTagged("KillBricks") do
setupKillbrick(part)
end
-- Listen for newly created killbricks and set them up
CollectionService:GetInstanceAddedSignal("KillBricks"):Connect(setupKillbrick)
-- The instance added event provides the newly added instance as the first argument, so we can connect it directly to the setup function