Client-Server replication issue when anchoring a Player Character

  1. What do you want to achieve?
    I want the player character to be anchored when they get “tagged” by another player.

  2. What is the issue?
    The issue is to do with replication, on every other client and the server the character is anchored in the same spot, however for the anchored player, they appear in a different position if they were moving when they got tagged.


  3. What solutions have you tried so far?
    I’ve searched for solutions and asked for advice from other devs, so far I have tried anchoring on both the server and the client side, I’ve tried only anchoring the HumanoidRootPart, I’ve tried disabling AutomaticScalingEnabled in the humanoid, I’ve messed around with changing network ownership and I’ve also tried “correcting” the HumanoidRootPart CFrame by telling the local player to move it’s CFrame to the position that the Server sees it’s CFrame via a remote event (worked in some use cases but not in all positions and was also very clunky)

below I’ll put the parts of the Code that I think are relevant, if you think I should post the full code (150+ lines) I will.

Module in ServerScriptService:

local function anchorPlayer(plr : Player, anchorStatus : boolean)
	if not char then
		--Find char
		char = plr.Character or plr.CharacterAdded:Wait()
	end
	
	if char then
		--Anchor children
		for _, obj in char:GetChildren() do
			if obj:IsA("BasePart") then
				obj.Anchored = anchorStatus
			end
		end
	end
	
	print(char:GetPrimaryPartCFrame().Position)
end

------------------------------

local function iceCubeProperties(plr : Player, anchorStatus : boolean , transparency : number, canCollide : boolean)
	local iceClone = char:FindFirstChild("IceCube")

	if iceClone then
		--Can add a tween here to give the icecube a melt effect
		--iceClone.Anchored = anchorStatus
		iceClone.Transparency = transparency
		iceClone.CanCollide = canCollide
	else
		warn("Icecube is not cloned in " ..plr.Name)
	end
end

-----------------------

tagFunctions.tagBegin = function(plr : Player)
	char = plr.Character or plr.CharacterAdded:Wait()
	hrp = char:WaitForChild("HumanoidRootPart")

	for _, obj in char:GetDescendants() do
		if obj:IsA("BasePart") then
			print("Gonna check now for touches")
			checkForTouch(plr, obj)
		
		elseif obj:IsA("Animator") then
			animator = obj
		end
	end
end

---------------------

tagFunctions.iceCubeClone = function(plr : Player)
	if iceCube then
		local iceClone = iceCube:Clone()
		iceClone.Anchored = false
		iceClone.CanCollide = false
		
		if not char then
			char = plr.Character or plr.CharacterAdded:Wait()
		end
		
		--Ice clone properties on start of round
		
		local weld : WeldConstraint = Instance.new("WeldConstraint")
		weld.Parent = iceClone
		weld.Part0 = iceClone
		weld.Part1 = char.PrimaryPart
		
		iceClone.Transparency = 1
		iceClone.CFrame = char.PrimaryPart.CFrame
		iceClone.Parent = char
		
	else
		warn("Icecube not found and is not cloned")
	end
end

----------------------

tagFunctions.tagEnable = function(plr : Player)
	local humanoid : Humanoid = char.Humanoid
	
	--humanoid.AutomaticScalingEnabled = false
	
	if tagged then
		--tagFunctions.hrpAnchor(true, plr)
		--tagFunctions.iceCubeClone()
		iceCubeProperties(plr, true, 0.5, true)
		anchorPlayer(plr, true)
		--playerTagged:FireClient(plr, hrp.CFrame)
		
		--animController.animPause(plr)
	end
	
	--// TEMPORARY - REPLACE WITH DISABLING WHEN THE ROUND ENDS \\--
	task.delay(5, function()
		tagFunctions.tagDisable(plr)
	end)
end

Server script in ServerScriptService:

local Players = game:GetService("Players")
local Teams = game:GetService("Teams")

local tagFunctions = require(script.TagFunctions)

Teams.Runners.PlayerAdded:Connect(function(plr)
	print(plr.Name .." Has been added to the " ..plr.Team.Name .." team" )
	tagFunctions.tagBegin(plr)
	tagFunctions.iceCubeClone(plr)
end)

Forgive me for the large amount of code :cold_sweat:

This is my first post on the Developer Forum so if I structured something wrong or there is a way I can improve my posts in the future then please let me know.
Thanks.

player characters are not meant to be anchored client side.
You are reinventing the wheel
Think about new players joining and state being not saved.

They aren’t anchored client-side, that’s just one of the things I tested when trying to fix this.
The players are both anchored and unanchored server side.

This issue is still unsolved and I have moved on since. If anyone knows any possible causes for this issue I’d appreciate the help as I’m interested in picking this project back up but can’t with this hurdle. :heart:

You could have the server fire the “tagged” client with the position it has for the client’s character, e.g:

--server
remoteEvent:FireClient(taggedPlr, taggedChar:GetPivot()) --fire "tagged" client with their character's position (from the server's perspective)

--client
local plr = game.Players.LocalPlayer
local char = player.Character or plr.CharacterAdded:Wait()

local function onRemoteEventFired(taggedCharPos)
	char:SetPivot(taggedCharPos) --set "tagged" client's character's position
end

remoteEvent.OnClientEvent:Connect(onRemoteEventFired)
1 Like