can you make the movement less choppy?

using UnityEngine;
using UnityEngine.Networking;
using System.Collections;
using System.Text;
using System.Collections.Generic;

public class FirstPersonController : MonoBehaviour
{
[Header("Movement Settings")]
[SerializeField] private float moveSpeed = 5f;
[SerializeField] private float sprintMultiplier = 1.5f;
[SerializeField] private float jumpForce = 5f;


[Header("Mouse Look Settings")]
[SerializeField] private float mouseSensitivity = 2f;
[SerializeField] private float maxLookAngle = 80f;

[Header("Network Settings")]
[SerializeField] private string serverUrl = "http://localhost:8000";
[SerializeField] private float networkUpdateRate = 0.1f; // Seconds between position updates
[SerializeField] private float movementUpdateRate = 0.1f; // Seconds between movement updates

private Camera playerCamera;
private float verticalRotation = 0f;
private Vector3 serverPosition;
private float lastNetworkUpdate;
private float lastMovementUpdate;

// Removed controlStates dictionary as we now work with actions
private string lastAction = "stop";
private bool lastJump = false;
private bool lastSprint = false;

private void Start()
{
    playerCamera = GetComponentInChildren<Camera>();
    if (playerCamera == null)
    {
        Debug.LogError("No camera found in children of FirstPersonController!");
        enabled = false;
        return;
    }

    Cursor.lockState = CursorLockMode.Locked;
    Cursor.visible = false;

    // Start position sync coroutine
    StartCoroutine(SyncPositionWithServer());
}

private void Update()
{
    HandleMouseLook();
    HandleMovementInput();

    // Send position updates to server periodically
    if (Time.time - lastNetworkUpdate >= networkUpdateRate)
    {
        SendPositionToServer();
        lastNetworkUpdate = Time.time;
    }
}

private void HandleMouseLook()
{
    // Horizontal rotation
    float mouseX = Input.GetAxis("Mouse X") * mouseSensitivity;
    transform.Rotate(Vector3.up * mouseX);

    // Vertical rotation (camera only)
    float mouseY = Input.GetAxis("Mouse Y") * mouseSensitivity;
    verticalRotation -= mouseY;
    verticalRotation = Mathf.Clamp(verticalRotation, -maxLookAngle, maxLookAngle);
    playerCamera.transform.localRotation = Quaternion.Euler(verticalRotation, 0f, 0f);

    // Send look direction to server if significant movement
    if (Mathf.Abs(mouseX) > 0.01f || Mathf.Abs(mouseY) > 0.01f)
    {
        SendLookDirectionToServer();
    }
}

private void HandleMovementInput()
{
    // Determine action based on input
    string action = "stop";
    bool jump = Input.GetKey(KeyCode.Space);
    bool sprint = Input.GetKey(KeyCode.LeftShift);

    bool forward = Input.GetKey(KeyCode.W);
    bool backward = Input.GetKey(KeyCode.S);
    bool left = Input.GetKey(KeyCode.A);
    bool right = Input.GetKey(KeyCode.D);

    // Decide action based on key presses
    if (forward && !backward)
    {
        action = "forward";
    }
    else if (backward && !forward)
    {
        action = "backward";
    }
    else if (left && !right)
    {
        action = "left";
    }
    else if (right && !left)
    {
        action = "right";
    }
    else if (jump)
    {
        action = "jump";
    }
    else
    {
        action = "stop";
    }

    // Check if movement state has changed
    bool shouldUpdate = action != lastAction || jump != lastJump || sprint != lastSprint;

    // Only send movement update if something changed or update timer elapsed
    if (shouldUpdate || Time.time - lastMovementUpdate >= movementUpdateRate)
    {
        SendMovementToServer(action, jump, sprint);
        lastMovementUpdate = Time.time;

        // Update last known states
        lastAction = action;
        lastJump = jump;
        lastSprint = sprint;
    }
}

private void SendMovementToServer(string action, bool jump, bool sprint)
{
    StartCoroutine(PostMovementRequest(action, jump, sprint));
}

private void SendPositionToServer()
{
    StartCoroutine(PostPositionRequest());
}

private IEnumerator PostPositionRequest()
{
    var posData = new CoordinateData
    {
        x = transform.position.x,
        y = transform.position.y,
        z = transform.position.z
    };

    string json = JsonUtility.ToJson(posData);

    using (UnityWebRequest request = new UnityWebRequest($"{serverUrl}/bot/coordinates", "POST"))
    {
        byte[] jsonBytes = Encoding.UTF8.GetBytes(json);
        request.uploadHandler = new UploadHandlerRaw(jsonBytes);
        request.downloadHandler = new DownloadHandlerBuffer();
        request.SetRequestHeader("Content-Type", "application/json");

        yield return request.SendWebRequest();

        if (request.result != UnityWebRequest.Result.Success)
        {
            Debug.LogWarning($"Position request failed: {request.error}");
        }
    }
}

private void SendLookDirectionToServer()
{
    Vector3 lookTarget = playerCamera.transform.position + playerCamera.transform.forward * 100f;
    StartCoroutine(PostLookRequest(lookTarget));
}

private IEnumerator SyncPositionWithServer()
{
    while (enabled)
    {
        using (UnityWebRequest request = UnityWebRequest.Get($"{serverUrl}/bot/coordinates"))
        {
            yield return request.SendWebRequest();

            if (request.result == UnityWebRequest.Result.Success)
            {
                string json = request.downloadHandler.text;
                CoordinateData coords = JsonUtility.FromJson<CoordinateData>(json);
                serverPosition = new Vector3(coords.x, coords.y, coords.z);
                transform.position = Vector3.Lerp(transform.position, serverPosition, 0.5f);
            }
            else
            {
                Debug.LogWarning($"Position sync failed: {request.error}");
            }
        }

        yield return new WaitForSeconds(networkUpdateRate);
    }
}

private IEnumerator PostMovementRequest(string action, bool jump, bool sprint)
{
    var moveData = new MovementData
    {
        action = action,
        jump = jump,
        sprint = sprint
    };
    string json = JsonUtility.ToJson(moveData);

    using (UnityWebRequest request = new UnityWebRequest($"{serverUrl}/bot/move", "POST"))
    {
        byte[] jsonBytes = Encoding.UTF8.GetBytes(json);
        request.uploadHandler = new UploadHandlerRaw(jsonBytes);
        request.downloadHandler = new DownloadHandlerBuffer();
        request.SetRequestHeader("Content-Type", "application/json");

        yield return request.SendWebRequest();

        if (request.result != UnityWebRequest.Result.Success)
        {
            Debug.LogWarning($"Movement request failed: {request.error}");
        }
    }
}

private IEnumerator PostLookRequest(Vector3 lookTarget)
{
    var lookData = new CoordinateData
    {
        x = lookTarget.x,
        y = lookTarget.y,
        z = lookTarget.z
    };

    string json = JsonUtility.ToJson(lookData);

    using (UnityWebRequest request = new UnityWebRequest($"{serverUrl}/bot/look", "POST"))
    {
        byte[] jsonBytes = Encoding.UTF8.GetBytes(json);
        request.uploadHandler = new UploadHandlerRaw(jsonBytes);
        request.downloadHandler = new DownloadHandlerBuffer();
        request.SetRequestHeader("Content-Type", "application/json");

        yield return request.SendWebRequest();

        if (request.result != UnityWebRequest.Result.Success)
        {
            Debug.LogWarning($"Look request failed: {request.error}");
        }
    }
}

[System.Serializable]
private class MovementData
{
    public string action;
    public bool jump;
    public bool sprint;
}

[System.Serializable]
private class CoordinateData
{
    public float x;
    public float y;
    public float z;
}
}