Wandering Enemies

Anybody else having the problem, with the waypoints that the character doesn’t wait before going to the next point?

    IEnumerator Patrol()
         {
            state = State.Patrolling;
            while (patrolPath != null)
            {
                //Set the nextposition the character should move to, to the position of the next waypoint
                 Vector3 nextWaypointPosition = patrolPath.transform.GetChild(nextWaypointIndex).position;

                 enemyMovement.SetDestination(nextWaypointPosition);

                if (Vector3.Distance(transform.position, nextWaypointPosition) <= waypointTolerance)
                {
                    nextWaypointIndex = CalculateNextWaypoint(nextWaypointIndex);
                }
                yield return new WaitForSeconds(5);
            }
        }

    int CalculateNextWaypoint(int currentWaypoint)
    {
        if(currentWaypoint == patrolPath.transform.childCount - 1)
        {
            return 0;
        }
        return currentWaypoint + 1;
    }

This is my current code, and have messed around with putting the wait statement in different lines (in the if statement mainly before calculating the next waypoint), however nothing seems to work. Any help here?

I am having the same problem. Even went back and copied the EnemyAI.cs code from the git repository and still am having the same problem with enemies not waiting at waypoints.

Yeah same, because my way is slightly different, I commented it out and just copy pasted bens way and still doesnt work. The thing is looking through the code, it doesn’t look like there is any issue. Reading line by line it reads correctly, i.e Go Position X if you’re in Y range of Position X, only calculate the next Position after Z Seconds. Since you have to wait for it to calculate the next Position, there is no way it should just run to the next Position without waiting. (Last bit was with having the yield WaitForSeconds before calculating nextWayPointIndex)

I think I finally found a solution to the NPC’s not stopping on their waypoints. I have also added in some code for ranged enemies who have a larger attack radius than a chase radius so they will stop when in range of you and attack and then return to patrol when you leave the attack radius. It needs some tweaking so they chase you as well, but I’ll get to that in another post soon.

I believe I also added code to make them walk when patrolling and run when chasing you, but I can’t remember if that was part of the lesson or something I added. Let me know if this helps any of you with this problem.

using System.Collections;
using UnityEngine;

namespace RPG.Characters
{
    [RequireComponent(typeof(Character))]
    [RequireComponent(typeof(WeaponSystem))]
    [RequireComponent(typeof(HealthSystem))]
    public class EnemyAI : MonoBehaviour
    {
        [SerializeField] float chaseRadius = 3f;
        [SerializeField] float waypointTolerance = 1.0f;
        [SerializeField] float waypointWaitTime = 3.0f;
        [SerializeField] float patrolMovementSpeed = 0.5f;
        [SerializeField] WaypointContainer patrolPath;

        float currentWeaponRange;
        float distanceToPlayer;
        int nextWaypointIndex;
        PlayerControl player;
        Character character;

        enum EnemyState { idle, attacking, patrolling, chasing }

        EnemyState state;

        private void Start()
        {
            state = EnemyState.idle;
            character = GetComponent<Character>();
            player = FindObjectOfType<PlayerControl>();
        }

        void Update()
        {
            // TODO Rewrite all the code for patrolling to include for ranged attackers.
            // minWeaponRange
            // maxWeaponRange
            // chaseRange
            // patrolling
            distanceToPlayer = Vector3.Distance(player.transform.position, transform.position);
            WeaponSystem weaponSystem = GetComponent<WeaponSystem>();
            currentWeaponRange = weaponSystem.GetCurrentWeapon().GetMaxAttackRange();

            // Adding the && state != .... to each of these fixed the problem with enemies not stopping on their waypoints for me
            bool inWeaponCircle = distanceToPlayer <= currentWeaponRange && state != EnemyState.attacking;
            bool inRangedCircle = distanceToPlayer <= currentWeaponRange && distanceToPlayer > chaseRadius && state != EnemyState.attacking;
            bool inChaseRing = distanceToPlayer > currentWeaponRange && distanceToPlayer <= chaseRadius && state != EnemyState.chasing;
            bool outsideChaseRing = distanceToPlayer > chaseRadius && distanceToPlayer > currentWeaponRange && state != EnemyState.patrolling;

            if (inWeaponCircle)
            {
                StopAllCoroutines();
                state = EnemyState.attacking;
                weaponSystem.AttackTarget(player.gameObject);
            }
            // Ranged attackers with currentWeaponRange > chaseRadius will stop and attack player with this block of code
            if (inRangedCircle)
            {
                StopAllCoroutines();
                state = EnemyState.attacking;
                character.SetDestination(transform.position);
                weaponSystem.AttackTarget(player.gameObject);
            }
            if (outsideChaseRing)
            {
                StopAllCoroutines();
                weaponSystem.StopAttacking();
                StartCoroutine(Patrol());
            }
            if (inChaseRing)
            {
                StopAllCoroutines();
                weaponSystem.StopAttacking();
                StartCoroutine(ChasePlayer());
            }           
        }

        IEnumerator Patrol()
        {
            state = EnemyState.patrolling;

            while (patrolPath != null)
            {
                Vector3 nextWaypointPos = patrolPath.transform.GetChild(nextWaypointIndex).position;
                character.AnimatorMaxPatrol = patrolMovementSpeed;
                character.SetDestination(nextWaypointPos);                
                yield return new WaitForSeconds(waypointWaitTime);
                CycleWaypointWhenClose(nextWaypointPos);
            }
        }

        void CycleWaypointWhenClose(Vector3 nextWaypointPos)
        {
            if (Vector3.Distance(transform.position, nextWaypointPos) <= waypointTolerance)
            {
                nextWaypointIndex = (nextWaypointIndex + 1) % patrolPath.transform.childCount;
            }
        }

        IEnumerator ChasePlayer()
        {
            state = EnemyState.chasing;
            while (distanceToPlayer >= currentWeaponRange)
            {
                character.AnimatorMaxPatrol = character.GetAnimatorMaxForward();
                character.SetDestination(player.transform.position);
                yield return new WaitForEndOfFrame();
            }
        }

        void OnDrawGizmos()
        {
            // Draw Attack Range Gizmo
            Gizmos.color = new Color(255f, 0f, 0f, .5f);
            Gizmos.DrawWireSphere(transform.position, currentWeaponRange);

            // Draw Chase Range Gizmo
            Gizmos.color = new Color(0f, 0f, 255f, .5f);
            Gizmos.DrawWireSphere(transform.position, chaseRadius);
        }
    }
}

Privacy & Terms