can you optimise my code? it should be more correct so that it is easy to maintain and so on

using UnityEngine;
using UnityEngine.UI;
using Unity.MLAgents;
using Unity.MLAgents.Sensors;
using Unity.MLAgents.Actuators;

public enum CharacterGroup
{
    Player,
    Ally,
    Enemy
}

public enum ControlMode
{
    Mouse,
    Joystick,
    AI
}

public class PlayerController : MonoBehaviour
{
    public CharacterGroup group;
    public ShootingAgent shootingAgent;
    public OpponentGenerator opponentGenerator;
    public VariableJoystick variableJoystick;
    public ControlMode currentControlMode = ControlMode.Mouse; // Default control mode is mouse
    public GameObject bulletPrefab;
    public string nickname = "lovekpek";
    public string brawlerName = "Nita";
    public int maxHealth = 3000; // Add a new variable for maximum health
    public int damage = 750; // Add a new variable for damage
    public bool damagePiercing = true;
    public float movementSpeed = 5f;
    public float aimingDistance = 5f;
    public float bulletSpeed = 10f;
    public int maxBullets = 3;
    public float reloadTime = 2f;
    public float shotDelay = 0.5f; // Delay between consecutive shots
    public float bulletWidth = 0.1f; // Bullet width
    [SerializeField] private HealthBar _healthbar;
    public Text healthText; // Reference to the UI text component for health display
    [SerializeField] private BulletBar _bulletbar;
    public Text bulletsText;
    public int currentHealth = 3000;
    public int currentBullets = 3;
    public Text speedText;

    private GameObject sightLine;
    private bool isAiming;
    private bool canShoot = true; // Flag to allow shooting
    private Vector2 aimDirection;
    private Vector2 lineEndPosition;
    private float currentDistance;
    //private int currentBullets;
    private float reloadTimer;
    private float shotTimer; // Timer for shot delay
    private bool hasFiredRecently; // New flag variable to track recent 
    private Vector2 movementInput;
    private float currentSpeed;

    private bool isPlayerControlled = false;

    private Collider2D lastCollision; // Class-level variable to store the last collision
    // Joystick control variables
    private float horizontalInput;
    private float verticalInput;

    private void Start()
    {
        currentBullets = maxBullets;
        UpdateBulletsText();
        switch (group)
        {
            case CharacterGroup.Player:
                isPlayerControlled = true;
                // Player-specific behavior
                break;
            case CharacterGroup.Ally:
                // Ally-specific behavior
                break;
            case CharacterGroup.Enemy:
                // Enemy-specific behavior
                break;
        }
    }

    private void Update()
    {
        if (currentBullets < maxBullets)
        {
            reloadTimer += Time.deltaTime;
            if (reloadTimer >= reloadTime)
            {
                reloadTimer = 0f;
                currentBullets++;
                UpdateBulletsText();
            }
        }
        else if (!isAiming && sightLine != null)
        {
            Destroy(sightLine);
        }

        healthText.text = currentHealth.ToString();
        _healthbar.UpdateHealthBar(maxHealth, currentHealth);

        if (isPlayerControlled)
        {
            /*// Add player position to observations
            Debug.Log(transform.position);

            // Get enemy positions from OpponentGenerator
            var enemyPositions = opponentGenerator.GetEnemyPositions();

            // Add enemy positions to observations
            foreach (var enemyPosition in enemyPositions)
            {
                Debug.Log(enemyPosition);
            }*/
            
            // Moving
            movementInput.x = Input.GetAxisRaw("Horizontal");
            movementInput.y = Input.GetAxisRaw("Vertical");
            movementInput.Normalize();
            currentSpeed = movementSpeed * movementInput.magnitude;
            Vector3 movement = new Vector3(movementInput.x, movementInput.y, 0f) * currentSpeed * Time.deltaTime;
            transform.position += movement;
            // Update speed text
            //speedText.text = "Speed: " + currentSpeed.ToString("F1");

            //Debug.Log(variableJoystick.Horizontal); // Add this line
            //Debug.Log(variableJoystick.Vertical); // Add this line
            switch (currentControlMode)
            {
                case ControlMode.Mouse:
                    if (Input.GetMouseButtonDown(0))
                    {
                        StartAiming();
                    }
                    else if (Input.GetMouseButtonUp(0))
                    {
                        StopAiming();
                    }
                    break;
                case ControlMode.Joystick:
                    //float horizontalInput = variableJoystick.Horizontal;
                    //float verticalInput = variableJoystick.Vertical;
                    if (Mathf.Abs(variableJoystick.Horizontal) > 0.1f || Mathf.Abs(variableJoystick.Vertical) > 0.1f)
                    //if (Mathf.Abs(horizontalInput) > 0.1f || Mathf.Abs(verticalInput) > 0.1f)
                    {
                        if (!isAiming)
                        {
                            StartAiming();
                        }
                    }
                    else
                    {
                        if (isAiming)
                        {
                            StopAiming();
                        }
                    }
                    break;


                case ControlMode.AI:
                    if (shootingAgent != null)
                    {
                        // Get the joystick control values from the ML agent
                        float horizontal = 0f;
                        float vertical = 0f;

                        // Retrieve the joystick control values from the ML agent
                        if (shootingAgent.GetComponent<BehaviorParameters>() != null)
                        {
                            var continuousActions = shootingAgent.GetComponent<BehaviorParameters>().brainParameters.vectorActionSize;
                            var actions = shootingAgent.GetAction();

                            if (actions.ContinuousActions.Length > 0)
                                horizontal = actions.ContinuousActions[0];

                            if (actions.ContinuousActions.Length > 1)
                                vertical = actions.ContinuousActions[1];
                        }

                        // Check if the joystick control values exceed the threshold
                        if (Mathf.Abs(horizontal) > 0.1f || Mathf.Abs(vertical) > 0.1f)
                        {
                            if (!isAiming)
                            {
                                StartAiming();
                            }
                        }
                        else
                        {
                            if (isAiming)
                            {
                                StopAiming();
                            }
                        }
                    }
                    break;


            }
            if (isAiming)
            {
                UpdateSightLine();
            }


            if (!canShoot)
            {
                shotTimer -= Time.deltaTime;
                if (shotTimer <= 0f)
                {
                    canShoot = true;
                }
            }

            if (!canShoot && hasFiredRecently)
            {
                shotTimer -= Time.deltaTime;
                if (shotTimer <= 0f)
                {
                    canShoot = true;
                    hasFiredRecently = false;
                }
            }
        }
    }

    private void StartAiming()
    {
        isAiming = true;

        // Destroy any existing SightLine object
        if (sightLine != null)
            Destroy(sightLine);

        sightLine = new GameObject("SightLine");
        LineRenderer lineRenderer = sightLine.AddComponent<LineRenderer>();
        lineRenderer.positionCount = 2;

        lineRenderer.startWidth = bulletWidth;
        lineRenderer.endWidth = bulletWidth;

        // Create a new material and set its color to white
        Material lineMaterial = new Material(Shader.Find("Sprites/Default"));
        lineMaterial.color = Color.white;

        lineRenderer.material = lineMaterial; // Assign the material to the line renderer

        lineRenderer.sortingLayerName = "Background"; // Set the sorting layer
        lineRenderer.sortingOrder = -1; // Set the sorting order to render behind the player

        lineRenderer.SetPosition(0, transform.position);
        lineRenderer.SetPosition(1, transform.position);

        currentDistance = aimingDistance;
    }

    private void StopAiming()
    {
        isAiming = false;
        Destroy(sightLine);

        if (canShoot && currentBullets > 0)
        {
            if (shotTimer <= 0f) // Check if shot delay has elapsed
            {
                FireBullet();

                currentBullets--;
                UpdateBulletsText();

                canShoot = false; // Set canShoot to false
                shotTimer = shotDelay; // Reset shot delay timer
            }
        }
    }

    private void UpdateSightLine()
    {
        //Vector2 aimDirection;
        if (currentControlMode == ControlMode.Mouse)
        {
            Vector2 mousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
            aimDirection = (mousePosition - (Vector2)transform.position).normalized;
        }
        else if (currentControlMode == ControlMode.Joystick)
        {   
            Debug.Log(variableJoystick.Horizontal); // Add this line
            Debug.Log(variableJoystick.Vertical); // Add this line
            aimDirection = new Vector2(variableJoystick.Horizontal, variableJoystick.Vertical).normalized;
        }
        else
        {
            // Handle AI logic here if needed
            aimDirection = Vector2.zero;
        }
        lineEndPosition = (Vector2)transform.position + aimDirection * currentDistance;
        /*Vector2 mousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        aimDirection = (mousePosition - (Vector2)transform.position).normalized;
        lineEndPosition = (Vector2)transform.position + aimDirection * currentDistance;*/

        LineRenderer lineRenderer = sightLine.GetComponent<LineRenderer>();
        lineRenderer.SetPosition(0, transform.position);
        lineRenderer.SetPosition(1, lineEndPosition);
    }

    public void FireBullet()
    {
        GameObject bullet = Instantiate(bulletPrefab, transform.position, Quaternion.identity);

        BulletController bulletController = bullet.GetComponent<BulletController>();
        bulletController.SetDirection(aimDirection);
        bulletController.SetSpeed(bulletSpeed);
        bulletController.SetMaxDistance(currentDistance);
        bulletController.SetGroup(group);
        bulletController.SetDamage(damage);
        bulletController.SetDamagePiercing(damagePiercing);
        
    }

    private void UpdateBulletsText()
    {
        bulletsText.text = currentBullets.ToString();
        _bulletbar.UpdateHealthBar(maxBullets, currentBullets);
    }

    private void OnTriggerEnter2D(Collider2D collision)
    {
        //Debug.Log(group); // Add this line
        if (group == CharacterGroup.Player && collision.CompareTag("Bullet") && collision.GetComponent<BulletController>().group == CharacterGroup.Ally)
        {
            // Ignore bullets from allies damaging the player
            return;
        }
        else if (group == CharacterGroup.Ally && collision.CompareTag("Bullet") && collision.GetComponent<BulletController>().group == CharacterGroup.Player)
        {
            // Ignore bullets from the player damaging allies
            return;
        }
        else if (group == CharacterGroup.Enemy && collision.CompareTag("Bullet") && collision.GetComponent<BulletController>().group == CharacterGroup.Player)
        {
            // Damage the enemy when hit by a player's bullet
            int bulletDamage = collision.GetComponent<BulletController>().GetDamage();
            bool bulletDamagePiercing = collision.GetComponent<BulletController>().GetDamagePiercing();
            TakeDamage(bulletDamage); // Remove the collision parameter
            //Debug.Log(bulletDamagePiercing);
            if (bulletDamagePiercing == false)
            {
                Destroy(collision.gameObject);
            }
            return;
        }
        // Handle damage and other collision logic
    }

    private void TakeDamage(int damageValue)
    {
        if (group == CharacterGroup.Enemy)
        {
            currentHealth -= damageValue;
            if (currentHealth <= 0)
            {
                // Enemy character has been defeated
                // Perform any necessary actions here (e.g., play a death animation, remove the character from the scene, etc.)
                Destroy(gameObject);
            }

            // Update the health bar and health text
            _healthbar.UpdateHealthBar(maxHealth, currentHealth);
            healthText.text = currentHealth.ToString();
        }
    }

    public void CollectObservations(VectorSensor sensor)
    {
        // Add player position to observations
        sensor.AddObservation(transform.position);

        // Get enemy positions from OpponentGenerator
        var enemyPositions = opponentGenerator.GetEnemyPositions();

        // Add enemy positions to observations
        foreach (var enemyPosition in enemyPositions)
        {
            sensor.AddObservation(enemyPosition);
        }
    }

    public void Shoot(float shootingAngle)
    {
        // Perform shooting logic based on the shooting angle
        // ...
    }
    public void RenderToTexture(RenderTexture renderTexture)
    {
        // Render the game view to the specified render texture
        RenderTexture currentRT = RenderTexture.active;
        RenderTexture.active = renderTexture;
        Camera.main.targetTexture = renderTexture;
        Camera.main.Render();

        // Reset the render texture and camera settings
        Camera.main.targetTexture = null;
        RenderTexture.active = currentRT;
    }
}