If you’re reading this, there probably aren’t very many posts yet. But don’t worry, you can be the first! Either create a new post or just reply to this one to say ‘hi’.
The problem with this bug fix is that it is defeating the idea of having a simple state machine, since we don’t use the ‘State’ enum anymore.
A state machine is not really necessary for such a simple behavior script, but now we have already broken something: having a weapon range larger than the chase change (typical for a ranged enemy) won’t work.
To fix that we can re-introduce a basic state machine with a switch statement. This makes a lot of repeated code,
but it is easier to avoid bugs:
//
// In EnemyAI.cs
//
// State made public for visibility in inspector
public enum State { idle, patrolling, attacking, chasing }
public State state = State.idle;
private void Update()
{
if (healthSystem.getIsAlive)
{
currentWeaponRange = weaponSystem.getCurrentWeaponConfig.getAttackRange;
distanceToPlayer = Vector3.Distance(player.transform.position, transform.position);
bool inWeaponRange = distanceToPlayer <= currentWeaponRange;
bool inChaseRange = distanceToPlayer > currentWeaponRange && distanceToPlayer <= chaseRadius;
bool outsideChaseRange = distanceToPlayer > chaseRadius;
switch (state)
{
case State.idle:
{
if (inWeaponRange)
{
StopAllCoroutines();
state = State.attacking;
weaponSystem.AttackTarget(player.gameObject);
}
if (outsideChaseRange)
{
StopAllCoroutines();
weaponSystem.StopAttacking();
StartCoroutine(Patrol());
}
if (inChaseRange)
{
StopAllCoroutines();
weaponSystem.StopAttacking();
StartCoroutine(ChasePlayer());
}
break;
}
case State.attacking:
{
if (inWeaponRange) { break; }
if (outsideChaseRange)
{
StopAllCoroutines();
weaponSystem.StopAttacking();
StartCoroutine(Patrol());
}
if (inChaseRange)
{
StopAllCoroutines();
weaponSystem.StopAttacking();
StartCoroutine(ChasePlayer());
}
break;
}
case State.patrolling:
{
if (inWeaponRange)
{
StopAllCoroutines();
state = State.attacking;
weaponSystem.AttackTarget(player.gameObject);
}
if (outsideChaseRange) { break; }
if (inChaseRange)
{
StopAllCoroutines();
weaponSystem.StopAttacking();
StartCoroutine(ChasePlayer());
}
break;
}
case State.chasing:
{
if (inWeaponRange)
{
StopAllCoroutines();
state = State.attacking;
weaponSystem.AttackTarget(player.gameObject);
}
if (outsideChaseRange)
{
StopAllCoroutines();
weaponSystem.StopAttacking();
StartCoroutine(Patrol());
}
if (inChaseRange) { break; }
break;
}
}
}
}
And for more complex behaviors, I think I’ll consider using this: