Server-Authoritative Movement: "Reconciling" correct values

Howdy!

I’ve been working on a system similar to Chickynoid in that it sends humanoid movement vectors, along with the current tick, validates the movement on the server, and then sends a message to the client acknowledging the movement request. Upon the client receiving the request, we calculate the current position on the server, and the position at which the client was when it sent the request. If there’s more than a 0.01 stud position error, or velocity, we will signal to the player to reconcile all requests after the current tick data.

From my understanding, on deterministic systems, it would be as easy as adding the inputs, re-simulating the position, and then tweening/pivoting the local player to their new simulated position, with the rollback data being adjusted as well. However, since I am using CharacterControllers, this system isn’t entirely easy to calculate where the character should be.

Here’s an example of the movement code, and the packet we send to the server:

local current_tick = workspace:GetServerTimeNow()

PlayerHandler.roll_back_data[current_tick] = {
	position = character.PrimaryPart.Position,
	velocity = character.PrimaryPart.AssemblyLinearVelocity,
	walk_speed = character.Controller.BaseMoveSpeed,
	movement_vector = character.Humanoid.MoveDirection,
}

character.Controller.MovingDirection = character.Humanoid.MoveDirection

packets.character.onCharacterMovement.send({
	start_tick = current_tick;
	move_direction = character.Humanoid.MoveDirection;
})

And here’s where we handle the server’s request to reconcile:

packets.character.serverComputeMovement.listen(function(data)
	if not data.server_position or not data.start_tick or not PlayerHandler.character or not PlayerHandler.character.Controller or not PlayerHandler.character.Humanoid then return end
	local find_rollback_data = PlayerHandler.roll_back_data[data.start_tick]
	if find_rollback_data then
		local calc_offset = find_rollback_data.position-data.server_position
		if calc_offset.Magnitude >= 0.01 then -- 0.001
			PlayerHandler.roll_back_data[data.start_tick] = nil
			PlayerHandler.character:PivotTo(CFrame.new(data.server_position))

			local last_tick = data.start_tick
			local last_position = data.server_position

			warn("reconcile")

			for this_tick, rollback_data in pairs(PlayerHandler.roll_back_data) do			
				if this_tick >= last_tick then -- Ensure this_tick is not smaller than last_tick
					-- TODO: Here is where we would recalculate all rollback datas' after the previous server communication
				end
			end
		else
			print("no reconcile needed")
		end


		PlayerHandler.character.Controller.MovingDirection = PlayerHandler.character.Humanoid.MoveDirection
		print(PlayerHandler.roll_back_data)

	end
end)

Any ideas would be helpful. I’ve tried calculating the new rollback position by using move_speed/time_held * move_vector, velocity prediction, etc. but nothing seemed to have been an efficient solution. Thanks in advance.

4 Likes

Did you ever figure it out?
I’m trying to implement something similar.

Have a good day.

Very, very late response; sorry.

For the best reconciliation, you need a robust snapshot system, I wrote a new one from scratch. You can use this as you want, but since it uses a plugin-context-only method you cannot use it for liveops projects.

It works without PausePhysics but the snapshot system gets wonky when offsets aren’t accounted for.

Test this out for yourself and see how it works for you, and if you have any questions.
Authoritative Movement.rbxl (89.5 KB)

Edit: For anyone reading this in the future, StepPhysics should make this easier in the future if it goes out of PluginContext only, hopefully Roblox provides an official resource in the future, but for now, create a system similar to this or use Chickynoid.

1 Like

No worries.

This definitely helped point me in the right direction, thanks! It definitely works very well for me; I just need to apply this to my racing game. I am just hoping Roblox makes StepPhysics usable in live games…

Have a great day!

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.