How to Move Player Character Movement to the Server (Server Authoritative Character Movement)

I’ll be teaching you how to move player character movement to the server, formally called server authoritative character movement.

Character movement is usually handled on the client so the player has instant control over what they do for a better gameplay experience. This means they can fly, walk through walls, or just walk super fast. But with this concept, the server becomes the single source of truth and handles things. This could be used for a makeshift anti-cheat system for these exploits.

While this is a great concept, be warned that this code is not a proper implementation, so it should never be used in actual games. It is only meant as a simple proof-of-concept. I actually found this out while doing random things with network ownership.

Why this implementation is bad:

  • Very hacky (this shouldn’t even work, why does it even work?)
  • No visual feedback for the player or rollback, movement appears delayed
  • No control or adjustment possible over how this works
  • Many other drawbacks

If you want a proper implementation, you’ll have to look elsewhere. Roblox is also currently working on a native implementation with a new script type named AuroraScript. Unofficial implementations are probably going to become obsolete soon.

With that out of the way, we can get to the bad implementation I was talking about. All you need to do is change the network owner of the BaseParts of the player’s character to the server. This includes any body parts, accessories, etc.

Create a script in ServerScriptService and put this code inside:

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

-- Set the network owner to the server
local function setNetworkOwner(part)
	if part:IsA("BasePart") then
		part:SetNetworkOwner()
	end
end

local function onDescendantAdded(descendant)
	setNetworkOwner(descendant)
end

local function onCharacterAdded(character)
	-- Allow the character to load into the workspace
	RunService.PostSimulation:Wait()

	-- Existing descendants
	for _, descendant in character:GetDescendants() do
		task.spawn(onDescendantAdded, descendant)
	end

	-- New descendants
	character.DescendantAdded:Connect(onDescendantAdded)
end

local function onPlayerAdded(player)
	-- Existing character
	if player.Character then
		onCharacterAdded(player.Character)
	end

	-- New characters
	player.CharacterAdded:Connect(onCharacterAdded)
end

-- Existing players
for _, player in Players:GetPlayers() do
	onPlayerAdded(player)
end

-- New players
Players.PlayerAdded:Connect(onPlayerAdded)

You can try the implementation in this game.

8 Likes

Or if you want a useful server authoritative player, you can just use Chickynoid by @MrChickenRocket

6 Likes

This idea is not uselless and not just for experiments, in fact most 3A games nowdays use this solution, its called server authoritative movement.

The way you solve the movement delay on your screen is actually a bit tricky, you instead create a client sided character and when you press an input you move it, while also sending that same input to the server so it can be executed on the server character. This way the character movement feels responsive

Like @noblemaxx said, you can use chickynoid if you are looking for this, its optimized and works smoothly.

6 Likes

It sucks that ROBLOX applies insane delay and smoothing from the server to the client, it could probably be fixed with a custom system (which is what i plan to do.)

Thanks for this!

Should i set the players movement type to Scriptable for server authoritative movement?
and if i do, how should i do the players movement?

This one also just gets broken by holding a tool
Maybe having custom system like chickynoid is only way