"Attempt to index nil with Parent" on a part that exists

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.

However, I get this as an error.

Here’s the code, apologies if it’s a bit messy.

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.

Why are you looping through items then not using them?

This line: for i,v in pairs(hit.Parent.TrashWeld:GetChildren()) do gives you an I/V pair but you don’t actually use them in the loop?

The hit is a reference to the item that touched script,.parent.

You should be using the V from the loop instead.

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

The loop is looping through the children of hit.Parent.TrashWeld.

You are not checking the results of the loop. You are checking the item named Hit.

You need to use the V from the loop since that is the child of the hit.Parent.TrashWeld

Otherwise, it makes no sense.

Create and Script and paste this in it:



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

Maybe it will help it all make sense.

I should ask, why do you have a rope of length 9999999999999999999999999999999999999999999999999999999 in the first place?

Because this is scary… and may or may not be the issue

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)
2 Likes