Syncing a clientside part with a serverside part, using time

  1. What do you want to achieve?
    I’m trying to sync a localplayer part to the server part.

  2. What is the issue? Include screenshots / videos if possible!
    The client part isn’t syncing correctly to the server’s part.

  3. What solutions have you tried so far?
    I’ve tried to factor in latency and such, but nothing.

On the server i’m simply moving a part from StartPoint to EndPoint, the client also does the same.

When the server starts, we store the os.clock(). we are then moving the servers part also.

When a client joins, we network the servers time to the client, and deduct the clients time. With this, we can then calculate where the client’s part should be.

However, this doesn’t work, and the client’s part always falls behind.

– Server

local ServerPart = Instance.new("Part")
ServerPart.Anchored = true
ServerPart.Parent = workspace
ServerPart.BrickColor = BrickColor.new("Bright blue")

local Speed = 1
local Start = workspace:WaitForChild("StartPoint")
local End   = workspace:WaitForChild("EndPoint")
ServerPart.Position = Start.Position

local syncR = game.ReplicatedStorage.ClientSync
local RS = game:GetService("RunService")

local GameStartTime = os.clock()
local RunTime = .017

RS.Heartbeat:Connect(function(dt)

	local Dir = (End.Position - ServerPart.Position).Unit
	local NewPosition = ServerPart.Position + Dir * (Speed * RunTime)

	-- Clamp to prevent overshooting
	local DistanceToEnd = (End.Position - ServerPart.Position).Magnitude
	local MovementMagnitude = (NewPosition - ServerPart.Position).Magnitude
	if MovementMagnitude > DistanceToEnd then
		ServerPart.Position = End.Position
	else
		ServerPart.Position = NewPosition
	end

end)


game.Players.PlayerAdded:Connect(function(player)
	player.CharacterAdded:Connect(function()
		syncR:FireClient(player, GameStartTime)
	end)
end)

– Client (ReplicatedFirst)


local ClientPart = Instance.new("Part")
ClientPart.Anchored = true
ClientPart.Parent = workspace
ClientPart.BrickColor = BrickColor.new("Gold")

local Speed = 1
local Start = workspace:WaitForChild("StartPoint")
local End   = workspace:WaitForChild("EndPoint")

local syncR = game.ReplicatedStorage.ClientSync
local RS = game:GetService("RunService")
local RunTime = .017

local totalElapsedTime = 0

syncR.OnClientEvent:Connect(function(serverTime)

	if (os.clock() - serverTime) > 0 then
		totalElapsedTime = (os.clock() - serverTime)
	end
	
	print( "server time", totalElapsedTime )
	
	-- Estimate how far the server's part has moved in this time
	local predictedDistance = (Speed*RunTime) * (totalElapsedTime)
	local Dir = (End.Position - Start.Position).Unit
	ClientPart.Position = Start.Position + Dir * predictedDistance
	
	RS.Heartbeat:Connect(function(dt)

		local Dir = (End.Position - ClientPart.Position).Unit
		ClientPart.Position = ClientPart.Position + Dir * (Speed*RunTime)

	end)
end)

I’d really appreciate your feedback on why this isn’t working the way i want it to. Thank you.