I am teleporting the players’ characters to a specific location before moving the player to a specific table
--Teleport the player from NotInGame to a random Teleporter, then move the player to InGame
for _, player: Player in player_handler.PlayersNotInGame do
print("INITIAL: All Players not in game: ",player_handler.PlayersNotInGame);
if not player.Character then
return
end
((player.Character):FindFirstChild("HumanoidRootPart") :: BasePart).CFrame = CFrame.new(ChooseATeleporter().Position + HRP_OFFSET,minigame_model:FindFirstChild("OriginPoint").Position)
player_handler:MoveToInGame(player); -- The issue comes from this line
end
print("ENDING: Players in game: ",player_handler.PlayersInGame)
print("ENDING: Players not in game: ",player_handler.PlayersNotInGame)
end
for some reason, it refuses to teleport all the players, it only teleports either certain players.
When I remove the method call, it works flawlessly.
The issue: It looks like the method (the line with the error) causes the for loop to stop iteration or to skip certain players.
--The method
function player_handler:MoveToInGame(player: Player): ()
if table.find(self.PlayersNotInGame, player) then
table.insert(self.PlayersInGame, table.remove(self.PlayersNotInGame, table.find(self.PlayersNotInGame, player)))
end
end
It’s plausible that modifying the table during iteration is affecting returned elements, because table.remove shifts them to fill the created gap, e.g. 1, 2, 3 → 1, 3 → 1, 2.
local t = {"a", "b", "c", "d", "e", "f"}
for i, v in t do
print(i, v)
table.remove(t, i)
end
Perhaps remove players from the old table after the iteration, or cache a deep copy to remove from.
Side note
Nothing should go wrong if FindFirstChild() is omitted, at least the second one. The return is not checked, so you might as well write minigame_model.OriginPoint.Position. HumanoidRootPart should also not be missing unless you remove it yourself during the game, but a check doesn’t hurt.
local hrp = player.Character:FindFirstChild("HumanoidRootPart")
if hrp then ... end
function player_handler:MoveToInGame(player: Player): ()
local index = table.find(self.PlayersNotInGame, player)
if index then
local removedPlayer = table.remove(self.PlayersNotInGame, index)
table.insert(self.PlayersInGame, removedPlayer)
end
end
I was thinking about either cloning the array to iterate over it
There is also the possibility to iterate through the array backwards → table.remove(tbl, #tbl)
When I’m in a similar situation, I just traverse the table normally and empty the whole array afterwards. That should be the most practical way, provided that the loop doesn’t yield and open a chance for the array to expand or shrink during iteration.
The other truly safe option, as you said, requires a clone.