Issue with a unit's death animation--enemies keep triggering unit's other animations

So I’m encountering an issue with a unit’s death animation, and enemies continuing to attack the unit so it can’t fully play the animation.

All units have a boxcollider2D and are on a “unitCollisionLayer”. These units attract and collide with a swarm of enemies. When colliding, the units lose their health. This also triggers the unit attack animation (swinging a weapon). This works fine.

I want each unit to trigger its death animation (falling to the ground) when its health reaches zero. It’s a 2 second animation. After 2 seconds, the unit is supposed to destroy itself.

The problem is when the unit is swarmed by enemy and its health reaches zero, it only runs the very beginning of its death animation, but then straightens back up again because the enemies keep colliding with it. I’ve tried turning off the unit’s boxcollider as soon as it dies, and also moving the unit to another layer (a layer the enemy doesn’t interact with in the physics matrix.)

No matter what I do, it seems like the enemy still keeps targeting the unit even after its health is zero

I have a unit prefab with these methods:

    private void OnCollisionEnter2D (Collision2D collision)
    {
        if ((GameAssets.Instance.enemyLayerMask & 1 << collision.gameObject.layer) == 1 << collision.gameObject.layer) // so only collides with the enemy layer
        {
            if (!healthSystem.IsDead())
            { animator.SetTrigger("isAttacking"); }
        }
    }

  public void AnimateDeath()
    {
        animator.SetTrigger("isDying");
    }

This is in the unit’s HealthSystem script.

    private void HealthSystem_OnDied()
    {
            GetComponent<Collider2D>().enabled = false;
            // also tried changing the layer after death by using int noInteractionLayer = LayerMask.NameToLayer("noInteractionLayer"); but this didn't work
            gameObject.layer = noInteractionLayer;
            StartCoroutine(DeathAnimation());
        }
        else
        {
            Destroy(gameObject);
        }
    }

    private IEnumerator DeathAnimation()
    {

        unitAnimation.AnimateDeath();
        yield return new WaitForSeconds(2); // Wait until the animation is not playing anymore before destroying object
        Destroy(gameObject);
    }

then I have this on the enemy:

    private void OnCollisionEnter2D(Collision2D collision)
    {
        Unit unit = collision.gameObject.GetComponent<Unit>();

        if (unit != null)
        {
            // collided with a unit
            HealthSystem healthSystem = unit.GetComponent<HealthSystem>();
            healthSystem.Damage(10);
            Destroy(gameObject); //destroys the enemy
        }
    }

This is in the Enemy’s update looking for targets (on the UnitColliderLayerMask)

    private void LookForTargets()
    {
        float targetMaxRadius = 10f;
        Collider2D[] collider2DArray = Physics2D.OverlapCircleAll(transform.position, targetMaxRadius, GameAssets.Instance.unitColliderLayerMask);

        foreach (Collider2D collider2D in collider2DArray)
        {
            if (targetTransform == null)
            {
                targetTransform = collider2D.transform;
            }
            else
            {
                if (Vector3.Distance(transform.position, collider2D.transform.position) < Vector3.Distance(transform.position, targetTransform.position))
                {
                    //move closer
                    targetTransform = collider2D.transform;
                }
            }
        }

Enemy’s initial target is a central castle (targetTransform), but if there are units along the way, it will try to destroy those units.

I can’t seem to figure out how to stop the enemy from targeting the dead unit or ignore it so the can play its death animation before being destroyed.

Anybody ever run into an issue like this? Any advice appreciated, thanks!

Just have some IsDead flag your units can express that they said to true when they die, and just have your units check if the unit they’re targeting/attacking are dead or not.

Probably want to guard other parts of your code to check whether the unit is dead or not.

Hey thanks…so I have a method in the HealthSystem called isDead() that checks if the unit’s health is zero. Are you saying change this to a field or property instead of using a method to check the dead status?

Either/or, whether it’s a method or property probably doesn’t matter too much, just so long as it returns a boolean value other objects can check. Then it’s just a matter of checking or guarding certain parts of your logic with this property.

1 Like