Input not properly synchronized on server

Hi,

I am trying to implement some simple ARPG style movement where you hold the right mouse button and the player moves towards that direction but I am having an issue where the position on the client is de-synced and stutters every few frames. I am using an IInputComponentData with an InputEvent to send the movement command to the server. The logic basically is as follows:

  1. GhostInputSystemGroup: Reset the input event first and If mouse button is held, set it. If I don’t reset the input event, then the it remains set for multiple ticks.
  2. PredictedSimulationSystemGroup: If input event is set, process the input.

I was looking at the input event’s count from the editor while moving and on the client it cycles from 1 to 2 periodically while on the server it cycles from 0 to 1 periodically. This is especially strange to me since I am resetting the player input on every update in the GhostInputSystemGroup so I am not sure how it ever becomes 2. I am also not sure if this is related to the de-synced values or if it’s the expected behavior and something else is causing the de-sync. Here’s the code for the three systems:

[UpdateInGroup(typeof(GhostInputSystemGroup))]
public partial class GatherPlayerInputSystem : SystemBase
{
    private InputSystemActions _inputActions;

    //_inputActions is initialized and enabled in OnCreate - omitted for simplicity

    protected override void OnUpdate()
    {
		var playerEntity = SystemAPI.GetSingletonEntity<LocalPlayerTag>(); //Get the local player entity
		var playerInputRW = SystemAPI.GetComponentRW<PlayerInput>(playerEntity);
		playerInputRW.ValueRW = default; //If i don't do this it remains set for multiple ticks

		if (_inputActions.Player.Move.IsPressed())  //Mouse right click
		{
			playerInputRW.ValueRW.movementDirection = //..based on mouse position
			playerInputRW.ValueRW.movement.Set();
		}
    }
}

[UpdateInGroup(typeof(PredictedSimulationSystemGroup))]
[UpdateBefore(typeof(MovementSystem))]
public partial struct ProcessPlayerInputsSystem : ISystem
{
    public void OnUpdate(ref SystemState state)
    {
        foreach (var (inputRO, movementRW) in SystemAPI.Query<RefRO<PlayerInput>, RefRW<Movement>>().WithAll<Simulate>())
        {
            if (!inputRO.ValueRO.movement.IsSet)
            {
                movementRW.ValueRW.isMoving = false;
                continue;
            }

            movementRW.ValueRW.direction = inputRO.ValueRO.movementDirection;
            movementRW.ValueRW.isMoving = true;
        }
    }
}


[UpdateInGroup(typeof(PredictedSimulationSystemGroup))]
public partial struct MovementSystem : ISystem
{
	public void OnUpdate(ref SystemState state)
	{
     var deltaTime = SystemAPI.Time.DeltaTime;
		foreach (var (localTransformRW, movementRW) in SystemAPI.Query<RefRW<LocalTransform>, RefRW<Movement>>().WithAll<Simulate>())
     {
			if (movementRW.ValueRO.isMoving)
			{
				var velocity = movementRW.ValueRO.direction * movementRW.ValueRO.speed;
				localTransformRW.ValueRW.Position += velocity * deltaTime;
			}
		}
	}
}

Could anyone please help me figure out what is going on and how it could be fixed?

Thank you!

I think you probably shouldn’t use InputEvent for continuous input. Just set MoveDirection every frame (if not pressing down, set it to float3.zero) and don’t check isMoving

Thank you for your response. Yeah I did that and while it seems to be better overall I still get the stuttering.

My guess is that now the stuttering occurs because the player can change the movement direction faster than the server’s tick rate, so during partial simulation on the client the direction is different than the direction the server has during full tick simulation. Does that make sense or am I misunderstanding something?

Edit: Nevermind the change suggested actually fixed the problem and I didn’t test properly