Issue with teleporting and moving the players

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

As you can see here, Player1 and Player3 were moved correctly, while Player2 and Player4 got skipped.

Thank you

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

image

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
1 Like

Please try doing step by step, maybe will help.

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

Thank you

Do you have a good solution to that issue?

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)

What do you think?

1 Like

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.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.