I,v pairs loop fail [SOLVED]

So I want to make a coin spawn randomizer with some effects and stuff, making it so I can add as much zones as i can without changing the code. The code works but only works on one zone. If you can help me make the code so it works on both zones. Code is below.

wait(1)

local tweenservice = game:GetService("TweenService")
local tweeninfo2 = TweenInfo.new(0.5)
local tweeninfo1 = TweenInfo.new(1)
local spawnables = game.ReplicatedStorage.Spawnables
local num1 = 30 -- Amount that can be spawned in
local currency = "Visors" -- Currency given when visor is collected


for i,v in pairs(spawnables:GetChildren()) do
                local spawnzone = workspace:FindFirstChild("Spawnables"):FindFirstChild(v.Name)
                local spawnlimit = spawnzone:FindFirstChild("Spawned")
                local currencygiven = v:FindFirstChild("Value").Value
                print("loading ".. spawnzone.Name)

                while spawnlimit.Value < num1 do
                        deb = true
                        local cloned = v:Clone()
                        local creationtween = tweenservice:Create(cloned,tweeninfo2,{Transparency=0})
                        cloned.Parent = spawnzone
                        cloned.CFrame = spawnzone.CFrame * CFrame.new(math.random(-spawnzone.Size.X/2, spawnzone.Size.X/2),spawnzone.Size.Y,math.random(-spawnzone.Size.X/2, spawnzone.Size.X/2))
                        creationtween:Play()
                        cloned:FindFirstChild("1").Enabled = true
                        spawnlimit.Value += 1
                        if spawnlimit.Value > 25 then
                                print("Too many visors")
                        else
                                print("Spawned visor for ".. spawnzone.Name)
                        end

                        cloned.Touched:Connect(function(hit)
                                local collectedvalue = cloned:FindFirstChild("Collected")
                                if collectedvalue.Value == false then
                                        local plr = game.Players:FindFirstChild(hit.Parent.Name)
                                        local leaderstats = plr:FindFirstChild("leaderstats")
                                        local points = leaderstats:FindFirstChild(currency)
                                        local removaltween = tweenservice:Create(cloned,tweeninfo1,{Transparency=1})
                                        print(hit.Parent.Name.." collected a visor from ".. spawnzone.Name )  
                                        collectedvalue.Value = true
                                        cloned:FindFirstChild("2").Enabled = true
                                        cloned:FindFirstChild("1"):Destroy()
                                        points.Value += currencygiven
                                        spawnlimit.Value -= 1
                                        removaltween:Play()
                                        wait(1)
                                        cloned:FindFirstChild("2").Enabled = false
                                        wait(1)
                                        cloned:Destroy()
                                end


                        end)
                        wait(2)
                end
        end     


I’m thinking the i,v pairs aint working in this case. I’ve tried even using print function to see if both zones would get registered but only one gets registered.

Any help would be appreciated.
Script is up to date.

1 Like

So, do you want to find all possible zones that has v’s name (exactly v’s name), or do you want zones that would see if v’s name is inside of it’s name?

1st One. It finds all of the zones that are v’s name then does its thing (spawning coins / visors)

Firstly, it’s FindFirstChild. It’s going to get the very first child that it finds in the table that meets those conditions (and because there’s two instances with the same exact name, they won’t be able to randomize the two). So what you should’ve done is make another i,v pairs loop for the folder of zones, so that the coins would spawn dedicating to the zone.

Unless you want it randomized to be put in either zone, you can also do:

local zoneToPick = math.random(1, #workspace:FindFirstChild("Spawnables"):GetChildren)

And use the zoneToPick (returns as a number) to find that zone in the folder. Something like this:

local zoneFolder = workspace:FindFirstChild("Spawnables"):GetChildren()
local rZones = math.random(1, #zoneFolder)
local zTP = zoneFolder[rZones]

To put it in your code, it could look something like this:

wait(1)

local tweenservice = game:GetService("TweenService")
local tweeninfo2 = TweenInfo.new(0.5)
local tweeninfo1 = TweenInfo.new(1)
local spawnables = game.ReplicatedStorage.Spawnables
local num1 = 30 -- Amount that can be spawned in
local currency = "Visors" -- Currency given when visor is collected


for i,v in pairs(spawnables:GetChildren()) do
                local spawnzone = workspace:FindFirstChild("Spawnables"):GetChildren()
                local rZones = math.random(1, #spawnzone)
                local zTP = spawnzone[rZones]
                
                local spawnlimit = zTP:FindFirstChild("Spawned")
                local currencygiven = v:FindFirstChild("Value").Value
                print("loading ".. spawnzone.Name)

                while spawnlimit.Value < num1 do
                        deb = true
                        local cloned = v:Clone()
                        local creationtween = tweenservice:Create(cloned,tweeninfo2,{Transparency=0})
                        cloned.Parent = zTP
                        cloned.CFrame = spawnzone.CFrame * CFrame.new(math.random(-spawnzone.Size.X/2, spawnzone.Size.X/2),spawnzone.Size.Y,math.random(-spawnzone.Size.X/2, spawnzone.Size.X/2))
                        creationtween:Play()
                        cloned:FindFirstChild("1").Enabled = true
                        spawnlimit.Value += 1
                        if spawnlimit.Value > 25 then
                                print("Too many visors")
                        else
                                print("Spawned visor for ".. spawnzone.Name)
                        end

                        cloned.Touched:Connect(function(hit)
                                local collectedvalue = cloned:FindFirstChild("Collected")
                                if collectedvalue.Value == false then
                                        local plr = game.Players:FindFirstChild(hit.Parent.Name)
                                        local leaderstats = plr:FindFirstChild("leaderstats")
                                        local points = leaderstats:FindFirstChild(currency)
                                        local removaltween = tweenservice:Create(cloned,tweeninfo1,{Transparency=1})
                                        print(hit.Parent.Name.." collected a visor from ".. spawnzone.Name )  
                                        collectedvalue.Value = true
                                        cloned:FindFirstChild("2").Enabled = true
                                        cloned:FindFirstChild("1"):Destroy()
                                        points.Value += currencygiven
                                        spawnlimit.Value -= 1
                                        removaltween:Play()
                                        wait(1)
                                        cloned:FindFirstChild("2").Enabled = false
                                        wait(1)
                                        cloned:Destroy()
                                end


                        end)
                        wait(2)
                end
        end
1 Like

image

Each iteration in the :GetChildren() table is immediately yielded by your while spawnlimit.Value < num1 loop.

You would need to use task.spawn(), or coroutine's, to make your code work as is. although I highly recommend rewriting your script to not require an absurd amount of threads in order to function as intended.

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

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

it is beyond what i can understand at the moment but ill try and implement this into my script

I don’t really see the problem with that, I think it’s not allowing it to find the instance? Because, is there an instanced inside of the spawnzone that has “Spawned” in it? If there is, you should do a WaitForChild.

If you could, can you explain what this would do as an example? I’m interested too and might need to implement this into some of my future codes as well.

Spawned is the numbervalue that counts how many has spawned. Its limit is 30. This is to control the amount of coin spawns

And is it in the spawnzone?

Probably a simple local spawnlimit = spawnzone:WaitForChild("Spawned") would do it.

OH WAIT WAIT, no no. Change the spawnzone to zTP. Because right now it’s pulling a value from a table. I believe

local spawnlimit = spawnzone:WaitForChild("Spawned") -- because spawnzone is a table, we're literally pulling a value that's not inside of this table.
-- instead it should've been:
local spawnlimit = zTR:WaitForChild("Spawned") -- since this is the actual instance with the limit

if you want me to compile the thing into a model and ill send it you
thats fine

It should work though, looking at that common/obvious mistake. Does it work now?

Take this script for instance.

for i = 1, 10 do
	while true do
		print (i)
		
		task.wait (i * 0.10)
	end
end

I want it to continuously print out the numbers from 1 to 10, but the first while true loop immediately yields the thread, making it so only “1” is printed forever.

image

However, as soon as I implement task.spawn, or coroutine.wrap, the script works as I want it to.

for i = 1, 10 do
	task.spawn (function ()
		while true do
			print (i)

			task.wait (i * 0.10)
		end
	end)
end
for i = 1, 10 do
	coroutine.wrap (function ()
		while true do
			print (i)

			task.wait (i * 0.10)
		end
	end)()
end

image

Different script, but the concept still applies to the problem presented in this post.

1 Like

That’s actually useful in some scenarios, making it more easier and faster to code, but then what’s the difference between task.spawn and corotine.wrap?

At the surface, there really isn’t a difference between the two. Personally, I always use task.spawn when I need to solve a problem that requires multi-threading. However, coroutine comes with some features that allow more control over the thread.

It’s possible to yield a thread within the coroutine, or completely terminate the thread entirely. If you need this functionality - use coroutine. If you don’t care / don’t need it, then task.spawn the simpler solution.

1 Like

https://www.roblox.com/library/9789785629/Testing

Here is the model if u want to modify it. Includes the original script

Does it work, though? That’s the main thing that we want right now, for you.

Yeh it does but doesnt do it for both zones