Enemies never leaving aggro state

Gettign the same error as many others. This is my current AIController:

using UnityEngine;
using RPG.Combat;
using RPG.Core;
using RPG.Movement;
using RPG.Attributes;
using GameDevTV.Utils;

namespace RPG.Control
{
    public class AIController : MonoBehaviour
    {
        [SerializeField] float chaseDistance = 5f;
        [SerializeField] float suspicionTime = 3f;
        [SerializeField] float agroCooldownTime = 5f;
        [SerializeField] PatrolPath patrolPath;
        [SerializeField] float waypointTolerance = 1f;
        [SerializeField] float waypointDwellTime = 3f;
        [Range(0, 1), SerializeField] float patrolSpeedFraction = 0.2f;
        [SerializeField] float shoutDistance = 5f;

        LazyValue<Vector3> guardPosition;
        float timeSinceLastSawPlayer = Mathf.Infinity;
        float timeSinceArrivedAtWaypoint = Mathf.Infinity;
        float timeSinceAggrevated = Mathf.Infinity;
        int currentWaypointIndex = 0;

        Fighter fighter;
        Health health;
        Mover mover;
        GameObject player;

        void Awake()
        {
            fighter = GetComponent<Fighter>();
            health = GetComponent<Health>();
            mover = GetComponent<Mover>();
            player = GameObject.FindWithTag("Player");

            guardPosition = new LazyValue<Vector3>(GetGuardPosition);
        }

        Vector3 GetGuardPosition()
        {
            return transform.position;
        }

        void Start()
        {
            guardPosition.ForceInit();
        }

        void Update()
        {
            if (health.IsDead()) { return; }

            if (IsAggrevated() && fighter.CanAttack(player))
            {
                AttackBehaviour();
            }
            else if (timeSinceLastSawPlayer < suspicionTime)
            {
                SuspicionBehaviour();
            }
            else
            {
                PatrolBehaviour();
            }

            UpdateTimers();
        }

        public void Aggrevate()
        {
            timeSinceAggrevated = 0;
        }

        void UpdateTimers()
        {
            timeSinceLastSawPlayer += Time.deltaTime;
            timeSinceArrivedAtWaypoint += Time.deltaTime;
        }

        void PatrolBehaviour()
        {
            Vector3 nextPosition = guardPosition.value;

            if (patrolPath != null)
            {
                if (AtWaypoint())
                {
                    timeSinceArrivedAtWaypoint = 0;
                    CycleWaypoint();
                }

                nextPosition = GetCurrentWaypoint();
            }

            if (timeSinceArrivedAtWaypoint > waypointDwellTime)
            {
                mover.StartMoveAction(nextPosition, patrolSpeedFraction);
            }
        }

        bool AtWaypoint()
        {
            float distanceToWaypoint = Vector3.Distance(transform.position, GetCurrentWaypoint());
            return distanceToWaypoint < waypointTolerance;
        }

        void CycleWaypoint()
        {
            currentWaypointIndex = patrolPath.GetNextIndex(currentWaypointIndex);
        }

        Vector3 GetCurrentWaypoint()
        {
            return patrolPath.GetWaypoint(currentWaypointIndex);
        }

        void SuspicionBehaviour()
        {
            GetComponent<ActionScheduler>().CancelCurrentAction();
        }

        void AttackBehaviour()
        {
            timeSinceLastSawPlayer = 0;
            fighter.Attack(player);

            AggrevateNearbyEnemies();
        }

        void AggrevateNearbyEnemies()
        {
            RaycastHit[] hits = Physics.SphereCastAll(transform.position, shoutDistance, Vector3.up, 0);

            foreach (RaycastHit hit in hits)
            {
                AIController ai = hit.collider.GetComponent<AIController>();

                if (ai == null || ai == this) { continue; }

                ai.Aggrevate();
            }
        }

        bool IsAggrevated()
        {
            float distanceToPlayer = Vector3.Distance(player.transform.position, transform.position);
            return distanceToPlayer < chaseDistance || timeSinceAggrevated < agroCooldownTime;
        }

        // Called by Unity
        void OnDrawGizmosSelected()
        {
            Gizmos.color = Color.blue;
            Gizmos.DrawWireSphere(transform.position, chaseDistance);
        }
    }
}

Any ideas? Excluding itself from the aggro shout didnt work. :confused:

Ahh okay, so they dont aggrevate themselves but they DO aggrevate friends FOREVER. So if two are chasing you, you have to kill one to get the other back to patrol state? Any easy fix for this?

You never increment timeSinceAggrevated so once this enemy aggravates (Aggrevate() sets the value to 0), it never goes back to not being aggravated. Your check IsAggrevated() will then always return true, because timeSinceAggrevated is always less than agroCooldownTime

Since posting I added it to the UpdateTimers(), yet the problem persists.

OK, I’m not sure which issue we’re still looking at. Incrementing the timeSinceAggrevated should fix the ‘coming out of aggro’ issue. As for the other, the enemy doesn’t aggro itself because you exclude it from the nearby enemies list. Remove (ai == this) from this line if (ai == null || ai == this) { continue; } in the AggrevateNearbyEnemies() method

@bixxario’s advice will ensure that the character aggrevates himself, but the feedback loop is difficult to escape here. What we need to do is avoid calling AggrevateNearbyEnemies if WE can’t see the character (even if we’re actually Aggrevated.

        void AttackBehaviour()
        {
            timeSinceLastSawPlayer = 0;
            fighter.Attack(player);
            if(Vector3.Distance(transform.position, player.transform.position<chaseDistance) 
            {
                 AggrevateNearbyEnemies(); 
            }
        }

This should stop the feedback loop while still causing the enemy to chase you when in range.

But I can’t compare a Vector3 to a float, no?

This has to be the solution then, no? I’ll try it.

        void AttackBehaviour()
        {
            timeSinceLastSawPlayer = 0;
            fighter.Attack(player);

            if (Vector3.Distance(player.transform.position, transform.position) > chaseDistance)
            {
                AggrevateNearbyEnemies();
            }
        }

EDIT: It worked! Thank you! :slight_smile:

It should be less, not more, but that’s the idea.

Ahh yes! Thank you! Doh. :smiley:

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms