/// <summary>
    /// Check for an Enemy Base or Enemy Units near this unit.
    /// </summary>
    protected virtual void CheckForEnemies()
    {
        Collider[] hitColliders = Physics.OverlapSphere(this.transform.position, 20);
        foreach (var hitCollider in hitColliders)
        {
            if (hitCollider.GetComponent <BaseManager>())
            {
                if (hitCollider.GetComponent <BaseManager>().Team != this.Team && CanAttack())
                {
                    timeSinceLastAttack = 0f;
                    hitCollider.GetComponent <BaseManager>().TakeDamage(attackDamage);
                    target = hitCollider.gameObject;
                    State  = UnitManager.UnitStates.AttackingBase;
                    return;
                }
            }
            else if (hitCollider.GetComponent <UnitController>())
            {
                if (hitCollider.GetComponent <UnitController>().Team != this.Team && CanAttack())
                {
                    timeSinceLastAttack = 0f;
                    hitCollider.GetComponent <UnitController>().TakeDamage(attackDamage);
                    target = hitCollider.gameObject;
                    State  = UnitManager.UnitStates.AttackingUnit;
                    return;
                }
            }
        }

        if (Vector3.Distance(this.transform.position, manager.rivalBase.transform.position) <= 2)
        {
            target     = manager.rivalBase;
            this.State = UnitManager.UnitStates.AttackingBase;
        }
    }
 /// <summary>
 /// Change this unit's State to Dead if health is at/below 0.
 /// </summary>
 protected virtual void CheckForDeath()
 {
     if (healthPoints <= 0)
     {
         this.State = UnitManager.UnitStates.Dead;
     }
 }
 /// <summary>
 /// Change this unit's Attack Target to the unit that has successfully Taunted it.
 /// </summary>
 public virtual void BecomeTaunted(GameObject newTarget)
 {
     target     = newTarget;
     this.State = UnitManager.UnitStates.AttackingUnit;
     Debug.Log($"{this} is taunted by {newTarget}.");
     this.GetComponent <NavMeshAgent>().SetDestination(target.transform.position);
 }
 /// <summary>
 /// Receive Damage to this unit's healthPoints. Change State to Dead if HP <= 0.
 /// </summary>
 /// <param name="receivedDamage"></param>
 public virtual void TakeDamage(float receivedDamage)
 {
     if (healthPoints > 0)
     {
         this.healthPoints -= receivedDamage;
     }
     else
     {
         this.State = UnitManager.UnitStates.Dead;
     }
 }
    /// <summary>
    /// If this unit is in range, attack its current target. If target == null, target the rivalBase.
    /// </summary>
    protected virtual void Attack(string unitOrBase)
    {
        #region Early Break (Null Target/Cooldown Incomplete)
        if (!CanAttack() || target == null)
        {
            this.State = UnitManager.UnitStates.Searching;
            return;
        }
        #endregion

        this.GetComponent <NavMeshAgent>().SetDestination(target.transform.position);

        if (Vector3.Distance(target.transform.position, this.transform.position) <= maxAttackRange)
        {
            this.GetComponent <NavMeshAgent>().isStopped = true;
            timeSinceLastAttack = 0f;

            switch (unitOrBase)
            {
            case "unit":
                //Attack a Unit
                this.State = UnitManager.UnitStates.AttackingUnit;
                if (target.GetComponent <UnitController>())
                {
                    target.GetComponent <UnitController>().TakeDamage(attackDamage);
                }
                break;

            case "base":
                //Attack a building in the base
                this.State = UnitManager.UnitStates.AttackingBase;
                if (target.GetComponent <BaseManager>())
                {
                    target.GetComponent <BaseManager>().TakeDamage(attackDamage);    // Rival Base chooses a random Building to receive this damage
                }
                break;
            }
        }
    }
    // Update is called once per frame
    protected virtual void Update()
    {
        if (target != null)
        {
            this.GetComponent <NavMeshAgent>().SetDestination(target.transform.position);
        }
        else if (target == null)
        {
            this.State = UnitManager.UnitStates.Searching;
        }

        if (HasLowHealth())
        {
            State = UnitManager.UnitStates.Fleeing;
        }
        CheckForDeath();

        CheckForEnemies();

        switch (this.State)
        {
        case UnitManager.UnitStates.Searching:
            target = manager.rivalBase;
            this.GetComponent <NavMeshAgent>().SetDestination(target.transform.position);
            break;

        case UnitManager.UnitStates.AttackingUnit:
            Attack("unit");
            break;

        case UnitManager.UnitStates.AttackingBase:
            Attack("base");
            break;

        case UnitManager.UnitStates.Defending:
            Attack("unit");
            break;

        case UnitManager.UnitStates.Fleeing:
            //Get Back into the Action if health is at least half full
            if (!HasLowHealth())
            {
                this.State = UnitManager.UnitStates.Searching;
            }
            else
            {
                //Keep Fleeing
                target = manager.baseManager.gameObject;
            }
            break;

        case UnitManager.UnitStates.Taunting:
            Attack("unit");
            break;

        case UnitManager.UnitStates.Dead:
            DestroySelf();
            break;

        default:
            this.State = UnitManager.UnitStates.Searching;
            break;
        }
    }