Why is my for i,v loop not working properly?

Hello, I’m currently working on an update for my game, “BlockRun” and I’m scripting a system that when a part is touched, it waits 5 seconds before collisions turn off. Everything works, no errors in the output. Only one problem is, it sets the wrong part’s collision off. So for example, level 1 has a part called spawn location, and level 2 same thing. When level 1’s part is touched level 2’s part collison turns off.

Here is the full script.


local Workspace = game:GetService("Workspace")
local StarterGui = script.Parent.Parent

local MainUI = StarterGui.Main
local LevelTime = MainUI.LevelTime


local Levels = game.Workspace.Levels
local SLS

local Debounce = false
--//Level Controls

for i,v in pairs(Levels:GetDescendants()) do
	if v.Name == "SpawnLocationStart" then
		SLS = v
		task.spawn(function()
			SLS.Touched:Connect(function(Hit)
				if Hit.Parent ~= nil and Hit.Parent:FindFirstChild("Torso") then
					if not Debounce then
						LevelTime.Visible = true
						Debounce = true
						for _ = 5,0,-1 do
							LevelTime.Text = _
							task.wait(1)
							if _ == 0 then
								SLS.CanCollide = false
								LevelTime.Visible = false
								task.wait(5)
								Debounce = false
							end
						end
					end
				end
			end)
		end)
	end
end

Try using ipairs instead of pairs

This is because “SLS” is changed and it is outside of the loop. That means every time SLS is called, the last one from the loop is affected instead.

Let’s step through your program. I’m going to skip unimportant instructions for what I believe the problem to be.

Firstly we create variable called SLS. We then loop through every descendant setting SLS to equal that descendant. SLS is being changed by every iteration through the loop. So now that I am skipping to the last iteration through your for loop, SLS is equal to Levels:GetDescendants()[#Levels:GetDescendants]. That means that any part of your script using SLS, is now equal to the last thing your loop did. To fix this, just replace every reference to SLS with v.

local Workspace = game:GetService("Workspace")
local StarterGui = script.Parent.Parent

local MainUI = StarterGui.Main
local LevelTime = MainUI.LevelTime


local Levels = game.Workspace.Levels
--//Level Controls

for i,v in pairs(Levels:GetDescendants()) do
	if v.Name == "SpawnLocationStart" then
            local Debounce
			v.Touched:Connect(function(Hit)
			if Hit.Parent ~= nil and Hit.Parent:FindFirstChild("Torso") then
				if not Debounce then
					LevelTime.Visible = true
					Debounce = true
					for _ = 5,0,-1 do
						LevelTime.Text = _
						task.wait(1)
						if _ == 0 then
							v.CanCollide = false
							LevelTime.Visible = false
							task.wait(5)
							Debounce = false
						end
					end
				end
			end
		end)
	end
end

It’s also worth noting that you don’t need a task.Spawn(). The .Touched essentially does that for you anyways.

I also moved the scope of the debounce otherwise you would run into a similar issue with that

Your saying the problem right here:

Why don’t you just give them both unique names?

task.spawn() isn’t necessary in this instance as connected callback functions execute in their own threads anyway.