How would I loop a GetDescendants() loop?

Howdy,

I have this script that loops through all the items in the Workspace. However, the loop doesn’t seem to work on the condition of “if v.Name == "Ending" then”.

I basically clone a map from RepStorage and into the workspace. I think the fact that the map was not originally in the workspace might have something to do with it. Although, I am unsure how to fix it.

Script
for i,v in pairs(game.Workspace:GetDescendants()) do
	if v:IsA("BasePart") then
		v.CastShadow = false
	end
	if v.Name == "Ending" then
		v.Touched:Connect(function(h)
			if h.Parent:FindFirstChild("Humanoid") then
				touched(h)
			end
		end)
	end
	wait(0.01)
end

(The touched(h) runs a function that teleports the player to a location. This is the thing that is not working. The player does not get teleported)

1 Like

I am a little confused as to why there is a touched function inside of a for loop. When the script has looped through everything in the workspace and it’s descendants, it will not fire anymore and hence the touched function won’t work.

2 Likes

It worked before, when the map was originally in the workspace.

I am wondering how I could loop this loop, or make it repeat indefinitely. Or even better, something to check if the ‘Ending’ part is in workspace, and if it is, continue with the Touched function

1 Like

You could always put it in a while true loop.

2 Likes

Update: I have put it into a while true loop, yet nothing seems to be working. The player still doesn’t get teleported.

Script
while wait() do
	repeat 
	for i,v in pairs(game.Workspace:GetDescendants()) do
		if v:IsA("BasePart") then
			v.CastShadow = false
		end
		if v.Name == "Ending" then
			v.Touched:Connect(function(h)
				if h.Parent:FindFirstChild("Humanoid") then
					touched(h)
				end
			end)
		end
		end
	wait(0.02)
	until 2+2 == 5
end

(I know the until 2+2 == 5 may be silly, but it will still run indefinitely, right?)

I also replaced the while wait() do with the while true do loop, and it does nothing. Perhaps I am doing it wrong?

1 Like

Why would you have the touched event in a while true loop, do you want it to always be executing when touched or?

2 Likes

I would like the touched event to be running when the part is touched, yes. If you mean the while true do loop, then I don’t know :sweat_smile:

Not true. I’ve done this plenty of times and it’s worked just fine.

2 Likes

What…? Of course it will. There is nothing in their code that would be disconnecting .Touched(). When a loop ends, connections made inside of it will still be connected.

Not a good idea. You should not be using loops when there are events for this purpose.

The issue here is probably the amount of parts in workspace. Your code will wait 0.01 seconds after each iteration, so if you have a ton of instances in workspace that will add up pretty quickly. Try removing the wait at the end and seeing if it fixes anything.

2 Likes

Try this

for i, v in pairs(workspace:GetDescendants()) do
	if v:IsA('BasePart') then
		v.CastShadow = false
    	if v.Name == 'Ending' then
    		v.Touched:Connect(function(h)
    			if h.Parent:FindFirstChild('Humanoid') then
    				touched(h)
    			end
    		end)
    	end
	end
	wait(0.01)
end
1 Like

@Crrustyy Also, can you show the touched() function?

Of course,

function touched(h)
	local part = game.Workspace:WaitForChild("SpawnLocation")
	if h.Parent:FindFirstChild("Humanoid") then
		local humRoot = h.Parent:FindFirstChild("HumanoidRootPart")
		humRoot.CFrame = CFrame.new(part.Position + Vector3.new(0,5,0))
		local plr = game.Players:FindFirstChild(h.Parent.Name)
		game.ReplicatedStorage:FindFirstChild("NewLevel"):FireClient(plr)
		game.ReplicatedStorage:FindFirstChild("Reward"):FireClient(plr)
		h.Parent.Humanoid.WalkSpeed = 16
	end
end
1 Like

I think I’ve got an idea. We can make a variable named “endingPart” and set it to nil for now. We can use a ChildAdded event into the script, and detect what instance was added to the Workspace. If the instance’s name was “Ending”, then we can set the endingPart’s value to the instance and use game.Workspace:FindFirstChild(endingPart.Name) to connect the touched event and do it like that.

This still doesn’t work. Perhaps I am looping it wrong?

1 Like

can u show us the console or does it not do anything?

There doesn’t seem to be any errors, other than a frequent ‘module error’ (has nothing to do with my scripts)

1 Like

Try this updated code:

local function touched(h)
	if h.Parent:FindFirstChild("Humanoid") then
		local part = game.Workspace:WaitForChild("SpawnLocation")
		local humRoot = h.Parent:FindFirstChild("HumanoidRootPart")
		humRoot.CFrame = CFrame.new(part.Position + Vector3.new(0,5,0))
		local plr = game.Players:FindFirstChild(h.Parent.Name)
		game.ReplicatedStorage:FindFirstChild("NewLevel"):FireClient(plr)
		game.ReplicatedStorage:FindFirstChild("Reward"):FireClient(plr)
		h.Parent.Humanoid.WalkSpeed = 16
	end
end

for i,v in pairs(game.Workspace:GetDescendants()) do
	if v:IsA("BasePart") then
		v.CastShadow = false
	end
	if v.Name == "Ending" then
		v.Touched:Connect(touched)
	end
end

I have this code, but it doesn’t work. Is it close to what I need?

Summary
game.Workspace.DescendantAdded:Connect(function(v)
	if v.Name == "Ending" then
		v.Touched:Connect(function(h)
			if h.Parent:FindFirstChild("Humanoid") then
				touched(h)
			end
		
		end)
	end
end)

Also, I will try your script out now

@Crrustyy
There is nothing wrong with the loop itself, it’s the function that doesn’t work.

2 Likes

Update: It also doesn’t work. I honestly don’t know what went wrong, it works when the map is originally in the workspace and not cloned/pasted.

1 Like