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);
}
}
}