I’m trying to loop through a Zombie Spawning Queue table, but for some reason it will stop looping once there are 10 values left in the table. I don’t think it loops in order either, even with ipairs, because a value was removed from around the middle of the table.
Once I realized I had to remove the zombie from the queue table every time since it got spawned, I used table.remove(Global_Info.ZombieQueue, i). Before this, it worked completely fine (besides the fact that I forgot to remove the zombie from the zombie queue once it spawned of course), and I removed the line table.remove(Global_Info.ZombieQueue, i) to prove this, and it looped through the entire table, so the problem has something to do with removing zombies from the table.
I also tried using a while true do loop instead, using a counter variable to track what index to use, but that didn’t work either.
Here’s the spawning function:
--Constant spawning of zombies
local function ZombieSpawning()
--VARIABLES--
--LOGIC--
--Loop through zombie queue and spawn zombies
for i, zombieName in ipairs(Global_Info.ZombieQueue) do
--Make sure the function should run
if Global_Info.RoundInfo.Active == false or not CurrentMapFolder:FindFirstChildWhichIsA("Model") or not CurrentMapFolder:FindFirstChildWhichIsA("Model"):FindFirstChild("ZombieSpawns") then return end
--VARIABLES--
local CurrentMap = CurrentMapFolder:FindFirstChildWhichIsA("Model")
local ZombieSpawns = CurrentMap:FindFirstChild("ZombieSpawns")
--LOGIC--
--Spawn zombie
ZombieSpawnModule.IndividualSpawn(ZombieInfoModule.Info[zombieName], ZombieSpawns:GetChildren()[math.random(#ZombieSpawns:GetChildren())], Global_Info.Entrances)
table.remove(Global_Info.ZombieQueue, i)
--Cooldown
task.wait(Global_Info.RoundInfo.ZombieSpawnCooldown)
end
end
(If you need to know other code in scripts let me know)
ipairs stops iterating over the array when it encounteres a nil value, so if the for loop stops after the 10th iteration, it indicates that the 11th value stored at Global_Info.ZombieQueue is missing
The 11th value being nil can explain why using a while loop with a counter also didn’t work, since if the code running in the loop depends on there being a value (which it does since you are using zombieName), an error would occur which will stop the loop from continuing to iterate over the array
Essentially, this means that to fix your issue, you’ll need to investigate why the 11th value of the Global_Info.ZombieQueue array isn’t being set properly (or at all)
@Void_Trader I’ve just noticed that you’re removing values from the array while iterating over the same array:
I don’t recommend you do so, as it can cause problems to occur, and could be the cause of your issue. In your case, since you seem to be removing all of the array’s values, using table.clear after the for loop could fix the problem:
--Constant spawning of zombies
local function ZombieSpawning()
--VARIABLES--
--LOGIC--
--Loop through zombie queue and spawn zombies
for i, zombieName in ipairs(Global_Info.ZombieQueue) do
--Make sure the function should run
if Global_Info.RoundInfo.Active == false or not CurrentMapFolder:FindFirstChildWhichIsA("Model") or not CurrentMapFolder:FindFirstChildWhichIsA("Model"):FindFirstChild("ZombieSpawns") then return end
--VARIABLES--
local CurrentMap = CurrentMapFolder:FindFirstChildWhichIsA("Model")
local ZombieSpawns = CurrentMap:FindFirstChild("ZombieSpawns")
--LOGIC--
--Spawn zombie
ZombieSpawnModule.IndividualSpawn(ZombieInfoModule.Info[zombieName], ZombieSpawns:GetChildren()[math.random(#ZombieSpawns:GetChildren())], Global_Info.Entrances)
--Cooldown
task.wait(Global_Info.RoundInfo.ZombieSpawnCooldown)
end
table.clear(Global_Info.ZombieQueue) -- This will remove all values from the array, but will keep its allocated capacity
-- Global_Info.ZombieQueue = {} -- Alternatively, you can set the array to an empty table to completely reset it
end
Is there a way to use the normal in pairs() to counter this problem instead? If not, this will work, but it would be easier to work with if the zombie got removed from the zombie queue immediately after it spawns, without breaking the loop.
I also plan on being able to add zombies to the zombie queue in real time, meaning I can add zombies to the zombie queue whenever and it will be added to that loop. Is that possible?
Using pairs seems to work well when I test it, it’s iterating over the whole array even though the value is being removed, so that was a good idea
@Void_Trader The statement above is invalid because I’ve found the true cause of the issues you’re experiencing: You’re using table.remove to remove the value from the array (while iterating over the same array). The reason why I said what I said is becaused I accidentally used a different way to remove the value from the array within my test, which is: array[index] = nil, and it worked exactly as you desire: The for loop successfully iterated over the whole array, both when using ipairs or pairs, and printing the contents of the array after the for loop shows that it was completely emptied. You can run the following tests in a new baseplate to confirm what I’m saying:
Test 1:
local array = {3, 6, 9, 12, 15}
for i, v in ipairs(array) do
print(i, v) -- Doesn't print value 4 and 5
table.remove(array, i)
end
warn(array) -- Array wasn't emptied correctly, value 1 and 2 still exist
Test 2:
local array = {3, 6, 9, 12, 15}
for i, v in ipairs(array) do
print(i, v) -- Successfully prints all values
array[i] = nil
end
warn(array) -- Array was emptied correctly