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:
- 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.
- 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!