Передвижение в Unity netcode for gameobjects

Я пытаюсь изучать Netcode for gameobjects, и хочу использовать архитектуру с удалённым сервером. Я не хочу доверять клиенту поэтому хочу от клиента отсылать "сообщение о желании перемещения" а на сервере уже двигать игрока, собственно у меня все получилось: При подключении клиента я спавнюю префаб игрока (через сервер) и через дикшинари связываю объект игрока с клиентом. Далее на клиенте я считываю ввод с клавиш и отправляю ServerRPC с Vector3 в виде строки, а на сервере беру префаб игрока из дикта с ключем в виде ID игрока и двигаю его.

НО! если я в билде запускаю сервер и в эдиторе перемещаюсь то все ок, но если наоборот то клиент движется сильно медленнее чем если клиент на эдиторе. Собственно в этом и вопрос. в чем я ошибся, или может rpc для такого вообще не подходит и есть способ получше?

повторюсь я не хочу доверять клиенту и позволять ему двигать себя самому. код ниже, заранее спасибо за советы!

код клиента считывания ввода:

public class PlayerNetworkObject : NetworkBehaviour
{
    private void Update()
    {
        if (!IsOwner || !IsClient)
            return;

        var direction = Vector3.zero;

        if (Input.GetKey(KeyCode.W))
            direction += Vector3.forward;

        if (Input.GetKey(KeyCode.S))
            direction += Vector3.back;

        if (Input.GetKey(KeyCode.A))
            direction += Vector3.left;

        if (Input.GetKey(KeyCode.D))
            direction += Vector3.right;

        _serverManager.MoveServerRPC(direction.ToString(), new ServerRpcParams());
    }
}

Код ServerManager:

 public class ServerManager : NetworkBehaviour
{
    [Inject] private DiContainer container;

    [Header("Prefabs")]
    [SerializeField] private Transform playerMovementNetworkPrefab;

    private Dictionary<ulong, PlayerObjectsData> _playersTable;

    private void Start()
    {
        _playersTable = new Dictionary<ulong, PlayerObjectsData>();

        NetworkManager.Singleton.OnClientConnectedCallback += SpawnPlayerMovement;
    }

    #region Spawn
    
    public void SpawnPlayerMovement(ulong clientId)
    {
        if(IsClient)
            return;
        
        if (!_playersTable.ContainsKey(clientId))
        {
            var playerMovement = container.InstantiatePrefabForComponent<PlayerMovementNetwork>(playerMovementNetworkPrefab);
            playerMovement.GetComponent<NetworkObject>().Spawn(true);

            _playersTable.Add(clientId, new PlayerObjectsData()
            {
                playerMovementNetwork = playerMovement,
            });
        }
    }

    #endregion

    #region Movement

    [ServerRpc(RequireOwnership = false)]
    public void MoveServerRPC(string moveDirection, ServerRpcParams serverRpcParams)
    {
        var direction = StringToVector3(moveDirection);

        if (direction.magnitude > 1)
        {
            Debug.LogWarning($"Client {serverRpcParams.Receive.SenderClientId} trying to move too far!");
            return;
        }

        _playersTable[serverRpcParams.Receive.SenderClientId].playerMovementNetwork.Move(direction);

        //MoveClientRPC(moveDirection, new ClientRpcParams() { Send = new ClientRpcSendParams(){TargetClientIds = new []{serverRpcParams.Receive.SenderClientId}}});
    }

    [ClientRpc]
    private void MoveClientRPC(string moveDirection, ClientRpcParams clientRpcParams)
    {
        //_playersTable[clientRpcParams.Receive].Move(StringToVector3(moveDirection));
    }

    private Vector3 StringToVector3(string sVector)
    {
        // Remove the parentheses
        if (sVector.StartsWith("(") && sVector.EndsWith(")"))
        {
            sVector = sVector.Substring(1, sVector.Length - 2);
        }

        // split the items
        string[] sArray = sVector.Split(',');

        // store as a Vector3
        Vector3 result = new Vector3(
            float.Parse(sArray[0].Replace('.',',')),
            float.Parse(sArray[1].Replace('.',',')),
            float.Parse(sArray[2].Replace('.',',')));

        return result;
    }

    #endregion

}

Код перемещения игрока:

public class PlayerMovementNetwork : NetworkBehaviour
{
    [Inject] private ServerManager serverMovementManager;

    [SerializeField] private float speed = 3f;

    public void Move(Vector3 direction)
    {
        transform.position += direction.normalized * speed * Time.deltaTime;
    }
}

Ответы (0 шт):