Client-Server Position mismatch

I want to make a round system that teleports the player to a map (Not a different place). As the rounds happen, their is an inconsistency with client-server player positions. I have looked a a plethora of different post on this topic, but nothing has worked. I believe it has something to due with their being two players and one of the dies to the switch (stick). when this happens the other player goes invisible to other players but the invisible player sees himself wit everyone else.

Here is my script:

--Things--
switch = game.Workspace.AllTheSwitches.DefaultSwitch
text = game.ReplicatedStorage.Status
playing = script.PlayersInRound

ReplicatedStorage = game:GetService("ReplicatedStorage")
playerDiedEvent = ReplicatedStorage:WaitForChild("PlayerDiedEvent")

--Variables--
--Switch Hiding Variables--
Map = nil
--HidingPlace = nil
NeededClicks = nil
Clicks = nil
--Round Variables--
Settings = game.ServerStorage.RoundSettings
RoundTime = Settings.RoundLength.Value
IntermissionTime = Settings.Intermission.Value
MinPlayers = Settings.MinPlayers.Value
--Player Related Variables--
Players = game.Players:GetChildren()
plrDiedLOL = game.ServerScriptService.PlayerDeathDetection.NameOfPlayerWhoDIedLOL
plrDied = game.ReplicatedStorage.PlayerDied

--Functions--
--Player Functions--
game.Players.PlayerAdded:Connect(function(player)
	local val = Instance.new("BoolValue")
	val.Name = "inRound"
	val.Parent = player
end)

script.PlayerWhoEscaped:GetPropertyChangedSignal("Value"):Connect(function()
	local plater = game.Players:FindFirstChild(script.PlayerWhoEscaped.Value)
	if plater.inRound.Value == true then
		playing.Value = playing.Value - 1
	end
end)

game.Players.PlayerRemoving:Connect(function(player)
	playing.Value = playing.Value - 1
end)

local function onPlayerDied(playerName)
	print("Player " .. playerName .. " has died.")
end

game.Players.PlayerAdded:Connect(function(player)
	player.CharacterAdded:Connect(function(character)
		character.Humanoid.Died:Connect(function()
			local plrName = player.Name
			local plrInThisCase = game.Players:FindFirstChild(plrName)
			if plrInThisCase:FindFirstChild("inRound")  then
				if plrInThisCase.inRound.Value == true then
					playing.Value = playing.Value - 1
					print(plrName.." was in the round so I gotta do something now :(")
				else
					print("They wern't in the round so I don't really care Womp Womp")
				end
			end
		end)
	end)
end)

--Round Functions--
script.PlayerWhoEscaped:GetPropertyChangedSignal("Value"):Connect(function()
	playing.Value = playing.Value -1
end)

function CheckPlayers()
	print("Checking Players")
	wait(2)
	if script.InARound.Value == false then
		if #game.Players:GetChildren() >= MinPlayers then
			if script.roundStarting.Value == false then
				print("Starting Round")
				wait(1)
				StartRound()
				wait(1)
			end
		else
			text.Value = "Not enough players..."
			print("Waiting...")
		end
	end
end

function StartRound()
	script.roundStarting.Value = true
	for i = IntermissionTime, 0, -1 do
		wait(1)
		text.Value = "Round Will Begin in "..i.." Seconds."
		if #game.Players:GetChildren() >= MinPlayers then
			print("Starting Round")
			if i == 0  then
				playing.Value = script.PlayersInServer.Value
				for i, player in pairs(game.Players:GetChildren()) do
					player.inRound.Value = true
				end
				script.InARound.Value = true
				FindTheStick()
			end
		else
			text.Value = "Not enough players..."
			print("Waiting...")
			script.roundStarting.Value = false
			break
		end
	end
end

--script.InARound:GetPropertyChangedSignal("Value"):Connect(CheckPlayers)
script.PlayersInServer:GetPropertyChangedSignal("Value"):Connect(CheckPlayers)

function EndRound()
	print("EndRound Funcftion fired")
	if playing.Value < MinPlayers and script.InARound.Value == true then
		print("Less than enough players to conteniue, ending round")
		local sclone = game:FindFirstChild("sclone", true)
		wait(1)
		playing.Value = 0
		if game:FindFirstChild("sclone", true) then
			print("sclone")
			local sclone = game:FindFirstChild("sclone", true)
			if sclone.Parent:FindFirstChild("Humanoid") then
				print("sclone ahs parrent")
				local player = game.Players:FindFirstChild(sclone.Parent.Name)
				script.PlayerWhoFoundTheStick.Value = sclone.Parent.Name
				task.wait(0.1)
				sclone.Parent = player.Backpack
				task.wait(0.1)
				sclone:Destroy()
				game.Lighting.SwitchAtmospere:Destroy()
				game.Lighting.SwitchSky:Destroy()
				wait(5)
				game.ReplicatedStorage.RoundEnded:FireAllClients()
				wait(2)
			end
		end
		for i, player in pairs(game.Players:GetChildren()) do
			if player.inRound.Value == true then
				local char = game.Workspace:FindFirstChild(player.Name)
				char.Humanoid.WalkSpeed = 16
				if char.Humanoid.Health <= 0 then
					local hmnd = char.HumanoidRootPart
					hmnd.CFrame = CFrame.new(16.782, 34.706, -9.106)
					game.ServerScriptService["MainRoundScriptV.6ChatGPT"].SwitchFound.Value = false
				end

			end
		end
		script.InARound.Value = false
		script.roundStarting.Value = false
	end
end

script.InARound:GetPropertyChangedSignal("Value"):Connect(CheckPlayers)

playing:GetPropertyChangedSignal("Value"):Connect(EndRound)


--FindTheStick--
function FindTheStick()
	ResetGame()
	local sclone = switch:Clone()
	sclone.Handle.Position = Vector3.new(154.88, 22.679, 327.46)
	sclone.Handle.Anchored = false
	sclone.Parent = game.Workspace
	sclone.Name = "sclone"
	task.wait(1)
	if Map == 1 then
		for i, player in pairs(game.Players:GetChildren()) do
			local char = player.Character
			local hmnd = char.HumanoidRootPart
			hmnd.Position = Vector3.new(-46.635, 14.372, 370.734)
			hmnd.Position = hmnd.Position + Vector3.new(Random.new(8, -8), 0, Random.new(8, -8))
		end
		local HMitem = 16
		local HMitemS = game.Workspace.HouseMap.HMItems:GetChildren()
		print(HMitem)
		game.Workspace.HouseMap.HMItems:FindFirstChild("HM_"..HMitem).isthething.Value = true
		print(NeededClicks)
		task.wait(1)
		repeat
			if playing.Value < MinPlayers then
				print("Everyone died LOL")
				break
			end
			task.wait()
			if game.Workspace.HouseMap.HMItems:FindFirstChild("HM_"..HMitem).isthething.Value == true and game.Workspace.HouseMap.HMItems:FindFirstChild("HM_"..HMitem).clicked.Value == true then
				Clicks = Clicks + 1
				print(Clicks.. ", "..NeededClicks)
				wait(0.2)
				if Clicks == NeededClicks then
					if HMitem > 5  then
						local bushPos = game.Workspace.HouseMap.HMItems:FindFirstChild("HM_"..HMitem).CFrame + Vector3.new(0, 6, 0)
						sclone.Handle.CFrame = bushPos
					end
					if HMitem < 6 then
						local rockPos = game.Workspace.HouseMap.HMItems:FindFirstChild("HM_"..HMitem).paart.CFrame + Vector3.new(0, 3, 0)
						sclone.Handle.CFrame = rockPos
					end
				end
			end
		until Clicks == NeededClicks

	end
end

function ResetGame()
	Map = 1
	NeededClicks = math.random(1, 5)
	Clicks = 0
end


--function Round()
--	CheckPlayers()
--	FindTheStick()
--end
--while true do
--	task.wait()
--	if playing.Value == 0 then
--		Round()
--	end
--end






Everything works fine except of the invisible thing. I check the clients and server whilst doing a local server with two people.

If anyone needs explanation on how the script works, I can provide it.

This is also my first forum post so if I did something wrong, just tell me.

1 Like

this happened to me on a separate game, you need to use Character:PivotTo()
setting the cframe of the humanoidrootpart makes roblox get upset for some reason

try doing:

local target = CFrame.new(16.782, 34.706, -9.106)
char:PivotTo(target)
2 Likes

Ok, I will try that when I get baxk from school.

This is technically correct because it is the correct way to CFrame on the server but I will explain the bigger issue here in a second

The bigger issue here is you are using CFrame on the server. This is something that can easily be done on the client and is much recommended to use the client for this instead. I am going to post a tutorial place on how I think the best way to achieve this is. In this place when 2 or more players are detected, it immediately sends them all to In-Round platform, waits 60 seconds, sends them to the escaped platform, and after that it either keeps them at the escaped platform or teleports them back to In-Round along with any new characters who have been added into the game. It will only restart the game under these 2 conditions:

  1. If a new player joins the game
  2. If the round is not already in progress

I really hope this helps :slight_smile:
Tutorial Place.rbxl (57.6 KB)

So, I can do either one? I looked at the place and I see how you script works. However, if a can just do Character:PivotTo(), then I would want to do that.

1 Like

I’m happy you at least looked at the place and learned how it works. You can but you risk players not being teleported sometimes. By doing it on the client you should have the best performance and it should consistently work. I cannot guarantee that with doing it on the server because in the past I did and it would forget to teleport people every once in awhile

Ok, fair point. I will try to do that then. Thank you for the help.