Scripts interfering with each other

Hi.
I’m currently developing a dungeon crawler game and I’m stuck with a problem.
I have 2 scripts for the enemies, one for them to do a patrol and the other to chace the player when this one is spotted. The thing is the scripts are interfering with each other giving a weird behaviour. I was trying to keep them seperated without mixing both.
Anyone have any suggestion?

//Enemy patrol
[DefaultExecutionOrder(-100)]
public class EnemySimplePatrol : MonoBehaviour
{

    //Dictates wheter the agent waits on each node.
    [SerializeField]
    bool _patrolWaiting;

    //The total time we wait at each node.
    [SerializeField]
    float _totalWaitingTime = 3f;

    //The probability of switching direction.
    [SerializeField]
    float _switchProbability = 0.2f;

    //The list of all patrol nodes to visil.
    [SerializeField]
    List<Waypoint> _patrolPoints;

    //Private variables for base behavior

    NavMeshAgent _navMeshAgent;
    Animator anim;
    int _currentPatrolIndex;
    bool _travelling;
    bool _waiting;
    bool _patrolForward;
    float _waitTimer;


    public void Start()
    {
        _navMeshAgent = this.GetComponent<NavMeshAgent>();
        anim = GetComponent<Animator>();

        if (_navMeshAgent == null)
        {
            Debug.LogError("not attached to " + gameObject.name);
        }

        else
        {
            if (_patrolPoints != null && _patrolPoints.Count >= 2)
            {
                _currentPatrolIndex = 0;
                anim.SetBool("idle", true);
                SetDestination();
            }
            else
            {
                Debug.Log("Insufficient patrol points.");
            }

        }
    }

    public void Update()
    {

    
       
        //Check if we're close to the destination.
        if (_travelling && _navMeshAgent.remainingDistance <= 1.0f)
        {
            _travelling = false;
            anim.SetBool("idle", false);
            anim.SetBool("move", true);



            //If we're going to wait, then wait dumbass!
            if (_patrolWaiting)
            {
                _waiting = true;
                _waitTimer = 0f;
                anim.SetBool("idle", true);
                anim.SetBool("move", false);

            }
            else
            {
                
                ChangePatrolPoint();
                SetDestination();
            }
        }

        //Instead if we're waiting...
        if (_waiting)
        {
            _waitTimer += Time.deltaTime;
            if (_waitTimer >= _totalWaitingTime)
            {
                _waiting = false;
                anim.SetBool("move", true);
                anim.SetBool("idle", false);



                ChangePatrolPoint();
                SetDestination();
            }
        }
    }

    private void SetDestination()
    {
        if (_patrolPoints != null)
        {
            Vector3 targetVector = _patrolPoints[_currentPatrolIndex].transform.position;

            _navMeshAgent.SetDestination(targetVector);
            _travelling = true;

            ////anim.SetBool("idle", false);
            ////anim.SetBool("move", true);
            
           
        }
    }

    //Selects a new patrol point in the available list, but
    //also with a small probability allows for us to move forward or backwards.

    private void ChangePatrolPoint()
    {
        //Unity generate random number between 0 and 1
        if (UnityEngine.Random.Range(0f, 1f) <= _switchProbability)
        {
            //decides if go forward or backwards: whatever the value, make the oposite
            _patrolForward = !_patrolForward;
        }

        if (_patrolForward)
        {
            //if the patrolpoint exceedes patrolpoints.count, go backs to zero
            _currentPatrolIndex = (_currentPatrolIndex + 1) % _patrolPoints.Count;
        }
        else
        {
            if (--_currentPatrolIndex < 0)
            {
                _currentPatrolIndex = _patrolPoints.Count - 1;
            }
        }
    }
}

//Enemy chace player

public class EnemyScript : MonoBehaviour
{

    Animator anim;

    public float speed = 4;
    //follow player
    public float enemyDistanceRun = 5.0f; //radius to spot the player
    //--
    PlayerHealthScript phs;



    void Start()
    {
        anim = GetComponent<Animator>();

    }



    void Update()
    {



        if (phs == null)
        {

            phs = GameObject.Find("Player Character").GetComponent<PlayerHealthScript>();
            

        }


    }

         

    public void chasePlayer()
    {
            if (Vector3.Distance(phs.transform.position, this.transform.position) < 10) 
            {

                Vector3 direction = phs.transform.position - this.transform.position;
                direction.y = 0;

                this.transform.rotation = Quaternion.Slerp(this.transform.rotation, Quaternion.LookRotation(direction), 0.1f);



                if (direction.magnitude > 2)
                {
                    this.transform.Translate(0, 0, 0.05f);
                    anim.SetBool("chase", true);
                    anim.SetBool("attack", false);

                }

                else
                {
                    anim.SetBool("attack", true);
                    anim.SetBool("chase", false);
                    anim.SetBool("move", false);

                }
            }
            else
            {

                anim.SetBool("chase", false);
                anim.SetBool("attack", false);
            }

        }

I don’t think there is necessarily a problem with combining all your AI behaviour in the same script. Otherwise the two AI behaviours would need to communicate with one another to ensure they aren’t working on top of one another, but this feels a bit too tightly coupled.

An approach I would take is to have a script that handles the movement separate to the scripts that handle the AI behaviour. The latter of which would just call the methods from the movement script (passing in any necessary variables like a direction, target, etc) rather handling any of that themselves.

My personal method for this is to make a container script that holds a ScriptableObject ‘brain’ variable. The container script just has an update method that makes the brain ‘think’ and all your logic for AI is coded inside the scriptable object. This concept I learned from this video: Unite 2016 - Overthrowing the MonoBehaviour Tyranny in a Glorious Scriptable Object Revolution - YouTube

So to avoid behaviour scripts crossing wires, you would put all the behaviour for patrolling and chasing in one brain, and handle the swapping of states inside the brains’ own logic. The upside on top of that, is that you can reuse this setup for all your NPCs/Enemies/ETC (even the player), and just write new brains rather than new scripts to handle everything for each instance of different behaviour.

Let me know if you’ve got any questions.