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;
    }
}