Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

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

Discussion in 'Scripting' started by bullettea, Jul 19, 2023.

  1. bullettea

    bullettea

    Joined:
    Oct 24, 2019
    Posts:
    29
    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:

    Code (CSharp):
    1.  
    2.     private void OnCollisionEnter2D (Collision2D collision)
    3.     {
    4.         if ((GameAssets.Instance.enemyLayerMask & 1 << collision.gameObject.layer) == 1 << collision.gameObject.layer) // so only collides with the enemy layer
    5.         {
    6.             if (!healthSystem.IsDead())
    7.             { animator.SetTrigger("isAttacking"); }
    8.         }
    9.     }
    10.  
    11.   public void AnimateDeath()
    12.     {
    13.         animator.SetTrigger("isDying");
    14.     }
    15.  

    This is in the unit's HealthSystem script.
    Code (CSharp):
    1.  
    2.     private void HealthSystem_OnDied()
    3.     {
    4.             GetComponent<Collider2D>().enabled = false;
    5.             // also tried changing the layer after death by using int noInteractionLayer = LayerMask.NameToLayer("noInteractionLayer"); but this didn't work
    6.             gameObject.layer = noInteractionLayer;
    7.             StartCoroutine(DeathAnimation());
    8.         }
    9.         else
    10.         {
    11.             Destroy(gameObject);
    12.         }
    13.     }
    14.  
    15.     private IEnumerator DeathAnimation()
    16.     {
    17.  
    18.         unitAnimation.AnimateDeath();
    19.         yield return new WaitForSeconds(2); // Wait until the animation is not playing anymore before destroying object
    20.         Destroy(gameObject);
    21.     }

    then I have this on the enemy:

    Code (CSharp):
    1.     private void OnCollisionEnter2D(Collision2D collision)
    2.     {
    3.         Unit unit = collision.gameObject.GetComponent<Unit>();
    4.  
    5.         if (unit != null)
    6.         {
    7.             // collided with a unit
    8.             HealthSystem healthSystem = unit.GetComponent<HealthSystem>();
    9.             healthSystem.Damage(10);
    10.             Destroy(gameObject); //destroys the enemy
    11.         }
    12.     }
    This is in the Enemy's update looking for targets (on the UnitColliderLayerMask)
    Code (CSharp):
    1.  
    2.     private void LookForTargets()
    3.     {
    4.         float targetMaxRadius = 10f;
    5.         Collider2D[] collider2DArray = Physics2D.OverlapCircleAll(transform.position, targetMaxRadius, GameAssets.Instance.unitColliderLayerMask);
    6.  
    7.         foreach (Collider2D collider2D in collider2DArray)
    8.         {
    9.             if (targetTransform == null)
    10.             {
    11.                 targetTransform = collider2D.transform;
    12.             }
    13.             else
    14.             {
    15.                 if (Vector3.Distance(transform.position, collider2D.transform.position) < Vector3.Distance(transform.position, targetTransform.position))
    16.                 {
    17.                     //move closer
    18.                     targetTransform = collider2D.transform;
    19.                 }
    20.             }
    21.         }
    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!
     
    Last edited: Jul 19, 2023
  2. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    5,848
    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.
     
  3. bullettea

    bullettea

    Joined:
    Oct 24, 2019
    Posts:
    29
    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?
     
  4. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    5,848
    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.
     
    bullettea likes this.