Enemies chasing player upon death and towards patrol paths

Hi I got the health state to save and restore before following along with Sam but even after looking at his code in the git I don’t understand why he didn’t have the following bugs I had unless they weren’t tested for.

Which is that the enemies in my game kept chasing me after dying or if they had a patrol root they would float towards the next path they were set to follow.

This also happened after loading including the patrol root if they the player wasn’t nearby to them.

This is my health restore code:

public void RestoreState(object state)
        {
            _health = (float)state;

            if (_health <= 0)
            {
                PutInDeadState();
            }
        }
   private void PutInDeadState()
        {
            GetComponent<Animator>().SetTrigger("Die");
            GetComponent<ActionScheduler>().CancelCurrentAction();
            _isDead = true;
        }

To fix this I had to add additional bool checks, the first being in the fighters update adding the additional isdead check:
if (_targetHealth == null || _targetHealth.IsDead || GetComponent<Health>().IsDead) return;

Then in ai controllers PatrolBehaviour:
if (_patrolPath != null && GetComponent<Health>().IsDead == false)

This mostly fixed it except any enemies with a patrol path upon loading would move a few inches towards the next path before stopping.

Sam hasn’t got any of these additional checks so I don’t understand why he doesn’t have these bugs and why the enemy still slightly floats towards the next path upon reload.

At some point, (I can’t tell you which lecture), Sam adds this line to Mover’s Update()

navMeshAgent.enabled = !health.IsDead();

This does everything in one check.
If the AIController tries to move the character, it’s shut down the very next frame.
If the Fighter tries to move the character, it’s shut down the very next frame.
If the Fighter tries to SetTrigger(Attack), the trigger is ignored because the animator is in the Dead state which only has an enter transition, but no exit transitions.

1 Like

I just added the line that you mentioned:

navMeshAgent.enabled = !health.IsDead();

It stopped enemeis with patrol paths from moving, but they kept rotating towards my direction whilst dead on the floor, when I uncommented my changes, so I added my changes again.

It is working correctly now but I keep getting the following error messages:
"SetDestination" can only be called on an active agent that has been placed on a NavMesh.
"Resume" can only be called on an active agent that has been placed on a NavMesh.
"Stop" can only be called on an active agent that has been placed on a NavMesh

Hmmm I’ll have to check if there’s another thing in the code (it may surprise you, but I don’t have the entire RPG memorized. :).

Deactivating the AIController on death would also be a good fix… I’m at work, so don’t have access to the codebase, but try something in AIController like

void Awake()
{
     GetComponent<Health>().OnDeath+=DeactivateSelf;
}

void DeactivateSelf()
{
     GetComponent<ActionScheduler>().CancelCurrentAction();
     enabled=false;
}

(I can almost guarantee the specific events and methods are wrong here, but you should be able to figure out the events in question. If OnDeath is a UnityEvent, then change the += line to read

GetComponent<Health>().OnDeath.AddListener(DeactivateSelf);
1 Like

Damn here’s me thinking you were the RPG core combat encyclopedia, the illusion has been broken :joy:

I like the idea of using an event as it will be cleaner and easier to add more listeners if I ever wanted more things to happen upon death, however unless I missed it I don’t think there’s an event used for dying.

At least not at the stage I’m at in the course, I am going to come back and heavily refactor after completing this and the inventory course so Ill change it to an event then.

Although I’m not sure if disabling the components will stop the saving system from storing the changes.

I noticed the main cause for the error messages is because a fair few scripts are trying to move the enemy but since the navmesh was disabled it caused the errors.

So I commented out the disable of the navmesh agent in Mover:

 void Update()
        {
            //_navMeshAgent.enabled = !GetComponent<Health>().IsDead;

            UpdateAnimator();
        }

However I then noticed some other problems…

I noticed that in AIController it kept setting the player as a target when I was in range:

if (InAttackRangeOfPlayer() && _fighter.CanAttack(_player))
            {
                AttackBehaviour();
            }

In the fighters.cs CanAttack I added an additional bool check so it would return false if the the fighter is dead:

public bool CanAttack(GameObject combatTarget)
        {
            if (combatTarget == null || GetComponent<Health>().IsDead){ return false; }

            Health targetToTest = combatTarget.GetComponent<Health>();

            return targetToTest != null && targetToTest.IsDead == false;
        }

I also found in AIController the PatrolBehaviour kept calling StartMoveAction:
because the if check for time at waypoint was always true so I moved I nested the if check so it returns false if the enemy is dead.

 private void PatrolBehaviour()
        {
            Vector3 nextPositioin = _guardPosition;
            if (_patrolPath != null && GetComponent<Health>().IsDead == false)
            {
                if (AtWaypoint())
                {
                        _timeAtWaypoint = 0;
                        CycleWaypoint();
                }
                nextPositioin = GetCurrentWaypoint();

                if (_timeAtWaypoint > _waypointDwellTime)
                {
                    Debug.Log("Trying to follow patrol path");
                    _mover.StartMoveAction(nextPositioin, _patrolSpeedFraction);
                }
            }            
        }

It all appears to be working now, thanks again for your help and suggestions.

The hardest part is that the codebase changes as we move through the course, so sometimes I’ll mention a feature that you haven’t gotten to yet

Case in point. You will eventually have an OnDeath type event, not too many lectures hence.

1 Like

It’s ok I was joking, I’m finding your responses very helpful thank you.

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

Privacy & Terms