What I’m trying to do is detect if the Parent of a touched part (hit) has a child named “TrashWeld.” The TrashWeld part has RopeConstraints as children. Using a for loop, I tried to iterate through all the RopeConstraints, detecting if the Parent of either the Attachment0 or Attachment1 of those RopeConstraints has a Parent that is equal to the touched part.
script.Parent.Touched:Connect(function(hit)
if hit.Name == "Trash" then
--wait(2.5)
-- local weld = Instance.new("WeldConstraint", hit)
-- weld.Part0 = hit
-- weld.Part1 = script.Parent
--end
if hit.Parent:FindFirstChild("TrashWeld") ~= nil then
for i,v in pairs(hit.Parent.TrashWeld:GetChildren()) do
print(hit)
if hit.Parent ~= nil then
if hit.Parent.TrashWeld.RopeConstraint.Attachment1.Parent == hit or hit.Parent.TrashWeld.RopeConstraint.Attachment0.Parent then
hit.Parent.TrashWeld.RopeConstraint:Destroy()
end
wait(1)
local rope = Instance.new("RopeConstraint", hit)
rope.Name = "TrashtoHopperRope"
rope.Attachment0 = hit.Attachment0 or hit.Attachment1 or hit.Attachment
rope.Attachment1 = script.Parent.Attachment
rope.Length = 9999999999999999999999999999999999999999999999999999999
end
end
end
if hit:FindFirstChild("RopeConstraint") then
hit:FindFirstChild("RopeConstraint"):Destroy()
wait(1)
local rope = Instance.new("RopeConstraint", hit)
rope.Name = "TrashtoHopperRope"
rope.Attachment0 = hit.Attachment0 or hit.Attachment1 or hit.Attachment
rope.Attachment1 = script.Parent.Attachment
rope.Length = 9999999999999999999999999999999999999999999999999999999
end
end
end)
On line 10, I tried to add a print function that spit out the name of the touched part. It would always output “Trash” as expected. So the part clearly exists, the script for some reason just thinks that the Parent is nil.
I have to loop through all of them to find the one with the RopeConstraint/Attachment associated with hit. What do you mean I should be using v instead?
Most likely, either Attachment0 or Attachment1 don’t exist, causing the error if hit.Parent.TrashWeld.RopeConstraint.Attachment1.Parent == hit or hit.Parent.TrashWeld.RopeConstraint.Attachment0.Parent then
for _, Item in pairs(game.Workspace:GetChildren()) do
print("Child Of Workspace: "..string.upper(Item.Name))
end
for _, Item in pairs(game.Workspace:GetDescendants()) do
if Item.Parent.Name ~= "Workspace" then -- ignore items in the workspace
print(string.upper(Item.Name).." is a child of "..Item.Parent.Name)
end
end
The problem is that you’re inserting wait(X) calls into the function and assuming the hierarchy around hit has not been changed when the thread resumes. For instance, if the object that was hit gets destroyed, its Parent will be set to nil and all of its children will be removed. It might be getting touched by a part that gets deleted shortly after.
Here’s a cleaner implementation based on what you described at the beginning:
local part = script.Parent
local function onTouched(hit: BasePart)
if hit.Name ~= "Trash" then
return
end
local parent = hit.Parent
local trashWeld = parent and parent:FindFirstChild("TrashWeld")
if trashWeld then
for i, child in trashWeld:GetChildren() do
if child:IsA("RopeConstraint") then
local a0 = child.Attachment0
local a1 = child.Attachment1
if a0 and a0.Parent == hit then
-- Touched part is Attachment0!
elseif a1 and a1.Parent == hit then
-- Touched part is Attachment1!
end
end
end
end
end
part.Touched:Connect(onTouched)