For i, v in pairs not working properly

Hello, so I am basically making a developer product which reveals the correct tiles for 15 seconds then puts them back to normal after the timer. Unfortunately, it is doing it a bit by a bit, rather than doing it all at once.

If you are going to tell me to use a courotine (if that’s the fix), please be aware that I have 0 knowledge on how to use them so I will need guidance.

The local script:

local plr = game.Players.LocalPlayer
local mps = game:GetService("MarketplaceService")
local id = 1301857815

script.Parent.MouseButton1Click:Connect(function()
	mps:PromptProductPurchase(plr, id)
end)

game.ReplicatedStorage.revealSafe.OnClientEvent:Connect(function()
	for i, v in pairs(game.Workspace.Stage:GetChildren()) do
		if v.Mirror_1.Value.Value == true then
			v.Mirror_1.BrickColor = BrickColor.new("Lime green")
			v.Mirror_1.Material = Enum.Material.Neon
			wait(15)
			v.Mirror_1.BrickColor = BrickColor.new("Transparent")
			v.Mirror_1.Material = Enum.Material.Glass
		else
			if v.Mirror_1.Transparency == 1 then
				v.Mirror_1.BrickColor = BrickColor.new("Lime green")
				v.Mirror_1.Material = Enum.Material.Neon
				wait(15)
				v.Mirror_1.BrickColor = BrickColor.new("Transparent")
				v.Mirror_1.Material = Enum.Material.Glass
			end
		end
	end
end)

game.ReplicatedStorage.revealSafe.OnClientEvent:Connect(function()
	for i, v in pairs(game.Workspace.Stage:GetChildren()) do
		if v.Mirror_2.Value.Value == true then
			v.Mirror_2.BrickColor = BrickColor.new("Lime green")
			v.Mirror_2.Material = Enum.Material.Neon
			wait(15)
			v.Mirror_2.BrickColor = BrickColor.new("Transparent")
			v.Mirror_2.Material = Enum.Material.Glass
		else
			if v.Mirror_2.Transparency == 1 then
				v.Mirror_2.BrickColor = BrickColor.new("Lime green")
				v.Mirror_2.Material = Enum.Material.Neon
				wait(15)
				v.Mirror_2.BrickColor = BrickColor.new("Transparent")
				v.Mirror_2.Material = Enum.Material.Glass
			end
		end
	end
end)

Ok so, the issue is that you aren’t using a courotine. The thing is, I don’t know how to use them. BUT, another way (which i think does the same thing) is using task.delay

task.delay(Time,function()
        -- task to do
end)

https://developer.roblox.com/en-us/api-reference/lua-docs/Roblox-Globals

Still, I think a more experienced developer should help you use courontines. Until someone else helps, you can use task.delay

I think using task.spawn would work the best for you.

What it does is basically run code in the background while you can do something else.

Here is an example of it.


while true do
task.wait()
print(“hi”)
end
print(“This will never print, since it is below the while true loop”)



task.spawn(function()
while true do
task.wait()
print(“hi”)
end

print(“this will now print!”)

(Also everything isn’t correctly formatted since I’m on mobile)

Contrary to what the other replies say, the proper response here is not coroutines, spawn, or delay. Those all create new threads to be executed in parallel with the rest of the script. That has a time and a place, and it’s not what you need here. It would be the easiest solution, but it’s not the proper solution. What you need is to restructure your loop. Instead of this

for i,v in pairs(a) do
    -- do something
    wait(15)
    -- do something
end

You need this

for i,v in pairs(a) do
    -- do something
end
wait(15)
for i,v in pairs(a) do
    -- do something
end

I’ve done that with your code here, and unless I’ve made a mistake combining it together, it should be what you need.

local plr = game.Players.LocalPlayer
local mps = game:GetService("MarketplaceService")
local id = 1301857815

script.Parent.MouseButton1Click:Connect(function()
	mps:PromptProductPurchase(plr, id)
end)

game.ReplicatedStorage.revealSafe.OnClientEvent:Connect(function()
	local children = workspace.Stage:GetChildren()
	for i, v in pairs(children) do
		if v.Mirror_1.Value.Value == true then
			v.Mirror_1.BrickColor = BrickColor.new("Lime green")
			v.Mirror_1.Material = Enum.Material.Neon
		else
			if v.Mirror_1.Transparency == 1 then
				v.Mirror_1.BrickColor = BrickColor.new("Lime green")
				v.Mirror_1.Material = Enum.Material.Neon
			end
		end
		if v.Mirror_2.Value.Value == true then
			v.Mirror_2.BrickColor = BrickColor.new("Lime green")
			v.Mirror_2.Material = Enum.Material.Neon
		else
			if v.Mirror_2.Transparency == 1 then
				v.Mirror_2.BrickColor = BrickColor.new("Lime green")
				v.Mirror_2.Material = Enum.Material.Neon
			end
		end
	end

	wait(15)

	for i, v in pairs(children) do
		if v.Mirror_1.Value.Value == true then
			v.Mirror_1.BrickColor = BrickColor.new("Transparent")
			v.Mirror_1.Material = Enum.Material.Glass
		else
			if v.Mirror_1.Transparency == 1 then
				v.Mirror_1.BrickColor = BrickColor.new("Transparent")
				v.Mirror_1.Material = Enum.Material.Glass
			end
		end
		if v.Mirror_2.Value.Value == true then
			v.Mirror_2.BrickColor = BrickColor.new("Transparent")
			v.Mirror_2.Material = Enum.Material.Glass
		else
			if v.Mirror_2.Transparency == 1 then
				v.Mirror_2.BrickColor = BrickColor.new("Transparent")
				v.Mirror_2.Material = Enum.Material.Glass
			end
		end
	end
end)
4 Likes

If you read your code out loud to yourself, you may notice that the script changes only one tile and then waits 15 seconds before changing it back.

for i, v in pairs(game.Workspace.Stage:GetChildren()) do
	v.Mirror_1.BrickColor = BrickColor.new("Lime green")
	v.Mirror_1.Material = Enum.Material.Neon -- we're showing the tile
	wait(15) -- now we wait 15 seconds
	v.Mirror_1.BrickColor = BrickColor.new("Transparent") 
	v.Mirror_1.Material = Enum.Material.Glass -- we're hiding the tile
end -- now looping again!

If you don’t want to use task.spawn() or coroutine.new() you could just split the actions in to two loops (like shown in the above reply), one loop for showing all of the tiles, and one loop for hiding all of them.