Enemy Ai attack range

Hey guys so i have this ai script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CopAi : MonoBehaviour
    
{

    private UnityEngine.AI.NavMeshAgent navMesh;
    public Transform Player;
    public Transform[] randomPoints;

    protected Animator animator;

    private float playerDist, randomPointDist;
    public int currentRandomPoint;
    private bool chasing, chaseTime, attacking;
    private float chaseStopwatch, attackingStopwatch;

    public float perceptionDistance = 30, chaseDistance = 20, attackDistance = 1, walkVelocity = 2, chaseVelocity = 6, attackTime = 1.5f, enemyDamage = 50;

    public bool seeingPlayer;
    public float enemyLife;
    public float totalEnemyLife = 100;
    public string GameOverSceneName;
    

    void Start()
    {
        animator = GetComponentInChildren<Animator>();
        currentRandomPoint = Random.Range(0, randomPoints.Length);
        navMesh = transform.GetComponent<UnityEngine.AI.NavMeshAgent>();
        enemyLife = totalEnemyLife;
        animator.SetBool("isWalking", false);
    }

    void Update()
    {

        playerDist = Vector3.Distance(Player.transform.position, transform.position);
        randomPointDist = Vector3.Distance(randomPoints[currentRandomPoint].transform.position, transform.position);
        RaycastHit hit;

        Vector3 startRay = transform.position;
        Vector3 endRay = Player.transform.position;
        Vector3 direction = endRay - startRay;

        if (Physics.Raycast(transform.position, transform.forward, out hit, 1000) && playerDist < perceptionDistance)

        {
            Debug.DrawRay(transform.position, transform.forward, Color.red, 5, false);

            if (hit.collider.gameObject.CompareTag("Player"))
            {
                seeingPlayer = true;
            }
            else
            {
                seeingPlayer = false;
            }
        }

        if (playerDist > perceptionDistance)
            walk();

        if (playerDist <= perceptionDistance && playerDist > chaseDistance)
        {
            if (seeingPlayer == true)
                look();
            else
                walk();
        }

        if (playerDist <= chaseDistance && playerDist > attackDistance)
        {
            if (seeingPlayer == true)
            {
                chase();
                chasing = true;
            }
            else
            {
                walk();
            }
        }

        if (playerDist <= attackDistance && seeingPlayer == true)
            
        attack();

        if (randomPointDist <= 3)
        {
              
            currentRandomPoint = Random.Range(0, randomPoints.Length);
            walk();
        }

        if (chaseTime == true)
            chaseStopwatch += Time.deltaTime;

        if (chaseStopwatch >= 5 && seeingPlayer == false)
        {
            chaseTime = false;
            chaseStopwatch = 0;
            chasing = false;
        }

        if (attacking == true)
            attackingStopwatch += Time.deltaTime;

        if (attackingStopwatch >= attackTime && playerDist <= attackDistance)
        {
            attacking = true;
            attackingStopwatch = 0;
            PLAYER.life = PLAYER.life - enemyDamage;

            if (PLAYER.life < 5)
                Application.LoadLevel(GameOverSceneName);
            else if (attackingStopwatch >= attackTime && playerDist > attackDistance)
            {
                attacking = false;
                attackingStopwatch = 0;
            }

        }
    }

    void OnCollisionImpulse(Collision col)
    {
        if (col.gameObject.tag == "Player")
        {
            enemyLife -= 10;
            Debug.Log(name + "'s HP: " + enemyLife);
            if (enemyLife <= 0)
            {
                //animator.SetBool("Dying" , true);
                seeingPlayer = false;
                walkVelocity = 0;
                attackDistance = 0;
                chaseVelocity = 0;
                chaseDistance = 0;
                enemyDamage = 0;
                currentRandomPoint = 0;
            }
        }
    }

    void walk()
    {
        animator.SetBool("isWalking", true);
        if (chasing == false)
        {
            //animator.SetFloat("Speed", 0.5f);
            animator.SetBool("isAttacking", false);
            navMesh.acceleration = 4;
            navMesh.speed = walkVelocity;
            navMesh.destination = randomPoints[currentRandomPoint].position;

        }
        else if (chasing == true)
        {
            //animator.SetFloat("Speed", 0.5f);
            animator.SetBool("isAttacking" , false);
            chaseTime = true;
        }
    }

    void look()
    {
        
        navMesh.speed = 0;
        transform.LookAt(Player);
    }

    void chase()
    {
        //animator.SetFloat("Sprint", 0.4f);
        animator.SetBool("isWalking", true);
        animator.SetBool("isAttacking" , false);
        navMesh.acceleration = 8;
        navMesh.speed = chaseVelocity;
        navMesh.destination = Player.position;
    }

    void attack()
    {
        animator.SetBool("isWalking", false);
        animator.SetBool("isAttacking" , true);        
        navMesh.acceleration = 0;
        navMesh.speed = 0;
        attacking = true;
       
    }
    
}

But my character falls into my player in order to attack while i need him to have an attack range to keep a short distance between him and the player! I ve tried a lot of things but nothing worked as expected! so how can i do it?

Also the raycasting to track the player works but i would like to make something like a cone visualrange instead of just a straight line raycast! is there a way to do this as well?

You appear to call walk after calling attack, which sets your velocity back to a positive value.


You could also save a lot of performance simply by changing this line

 if (Physics.Raycast(transform.position, transform.forward, out hit, 1000) && playerDist < perceptionDistance)

To this line

 if (playerDist < perceptionDistance && Physics.Raycast(transform.position, transform.forward, out hit, 1000))

This is because the order of conditions matters, the new line will only raycast if required.