Teleporting many players to CFrame fails for some players

Our game Light Game is a game composed of several mini-games, and between each mini-game, players are teleported back to the lobby, where they must enter a zone in order to enter the next mini-game. For teleportation, we use Model:SetPrimaryPartCFrame on the players.

Recently, it has come to our attention that in rare cases*, some players would return to their original position in the matchmaking zone immediately upon getting teleported to the mini-game. In all cases, they would obtain the mini-game actions and tools in the lobby, which means that the issue is not caused by another system written by us.

The teleportation is pretty basic and happens in the following function** which is used to admit players into the game:

Admission = function(Player)
			local Char = Player.Character
			if not table.find(Playing, Player) and Char and Char.PrimaryPart and Char.Humanoid.Health > 0 then
				table.insert(Playing, Player)
				Player.Playing.Value = true
				local X = Game1.Area.Position.X + math.random(-Game1.Area.Size.X / 2 + 5, Game1.Area.Size.X / 2 - 5)
				local Z = Game1.Area.Position.Z + math.random(-Game1.Area.Size.Z / 2 + 5, Game1.Area.Size.Z / 2 - 5)
				local RandomPos = CFrame.new(X, Game1.Area.Position.Y, Z)
				Char:SetPrimaryPartCFrame(RandomPos)
				PlayerRemote:FireClient(Player, "PassPrompt", "DoubleSpeed")
				task.spawn(GiveGun, Player)
			end
		end

I would think that the issue might be happening because of high latency on the players’ end, or maybe anti-cheat acting, but again, it is the server that does the teleportation.

We are open to any-and-all possible fixes and ideas. Thank you for your support.

*It is worth noting that in an average server, around 50 players enter the matchmaking zone. 2-3 return due to the issue.

**The admission function is a bit different for every game mode, but the creation of the CFrame and the teleportation remain the same. The issue also happens in every game mode.

1 Like

PivotTo is a more performant replacement for SetPrimaryPartCFrame and does not change your code’s behavior. it’s suggested that it should be used for newer work.
Here’s an example I found that uses PivotTo for character teleportation:

local function doTeleport()
	local player = Players.LocalPlayer
	local character = player.Character
	if character and character.Parent then
		local currentPivot = character:GetPivot()
		character:PivotTo(currentPivot * CFrame.new(0, 0, -10))
	end
end
1 Like
for i,v in pairs(game.Players:GetPlayers()) do --adjust
	if v.Character then
		if v.Character.Humanoid then
			v.Character.Torso.CFrame = CFrame.new() --adjust
		end
	end
end

This should work

Do you have an anti cheat system in place for your game at the moment?

There are a couple solutions with the information given.

  1. repeatedly teleport the player to said location until the server can verify that they are close enough before giving tools.
Admission = function(Player)
			local Char = Player.Character
			if not table.find(Playing, Player) and Char and Char.PrimaryPart and Char.Humanoid.Health > 0 then
				table.insert(Playing, Player)
				Player.Playing.Value = true
				local X = Game1.Area.Position.X + math.random(-Game1.Area.Size.X / 2 + 5, Game1.Area.Size.X / 2 - 5)
				local Z = Game1.Area.Position.Z + math.random(-Game1.Area.Size.Z / 2 + 5, Game1.Area.Size.Z / 2 - 5)
				local RandomPos = CFrame.new(X, Game1.Area.Position.Y, Z)
				
				while true do
					Char:SetPrimaryPartCFrame(RandomPos)
					wait(1)
					if not Char.Parent or not Char.PrimaryPart then return end
					if Char.PrimaryPart and (Char.PrimaryPart.Position - RandomPos).Magnitude < 50 then
						break
					end
				end
				
				PlayerRemote:FireClient(Player, "PassPrompt", "DoubleSpeed")
				task.spawn(GiveGun, Player)
			end
		end
  1. Fire the player’s client with a RemoteEvent’s :FireClient() and pass the cframe for the localscript to teleport.

  2. Interface with the anti cheat? But, not sure if you have one in the first place.

2 Likes