Attacking while IsDead - Only one time

Hello I am working through the RPG Course and I have ran into an issue where the player attacks one more time after the enemy is dead. I have tried a few things to get it to stop, but no luck.

ezgif-5-ae33820a27

namespace RPG.Core
{
  public class Health : MonoBehaviour, ISaveable
  {
    [SerializeField] float healthPoints = 100f;
    [SerializeField] TakeDamageEvent takeDamage;

    [System.Serializable]
    public class TakeDamageEvent : UnityEvent<float>
    {
    }

    bool isDead = false;
    private void Start()
    {

    }

    public bool IsDead()
    {
      return isDead;
    }

    public void TakeDamage(float damage)
    {
      healthPoints = Mathf.Max(healthPoints - damage, 0);


      if (healthPoints <= 0)
      {
        DeathAnimation();
        takeDamage.Invoke(damage);
      }
      else
      {
        takeDamage.Invoke(damage);
      }

    }

    public void DeathAnimation()
    {
      
      if (isDead) return;
      isDead = true;
      GetComponent<Animator>().SetTrigger("die");
      GetComponent<ActionScheduler>().CancelCurrentAction();

    }

    public object CaptureState()
    {
      return healthPoints;
    }

    public void RestoreState(object state)
    {
      healthPoints = (float)state;
      if (healthPoints == 0)
      {
        DeathAnimation();
      }
    }
  }
}

Any thoughts on how to get that 2nd attack to not happen?

Nothing in the Health component is really going to help stop this, as the health is on the dead enemy, and the player’s Fighter is what’s doing the killling.

Here’s a slight mod I make in Fighter in Update() after determining if the target is not null

if(target.IsDead())
{
     target=null;
     GetComponent<Animator>().SetTrigger("stopAttack");
     return;
}

Thanks Brian!

That stopped the animation but it is still triggering Hit.

using System.Collections.Generic;
using UnityEngine;
using RPG.Movement;
using RPG.Core;
using System;

namespace RPG.Combat
{

  public class Fighter : MonoBehaviour, IAction
  {




    [SerializeField] Transform rightHandTransform = null;
    [SerializeField] Transform leftHandTransform = null;

    [SerializeField] weapon weapon = null;
    weapon currentWeapon = null;
    Health target;

    float timeSinceLastAttack = 0;

    private void Start()
    {
      EquipWeapon(weapon);

    }


    private void Update()
    {
      
      timeSinceLastAttack += Time.deltaTime;

      if (target == null) return;
      if (target.IsDead())
      {
       GetComponent<Animator>().SetTrigger("stopAttack");
       return;

              };

      if (!GetIsInRange())
      {
        GetComponent<Mover>().MoveTo(target.transform.position);
      }
      else
      {
       
        GetComponent<Mover>().Cancel();
        AttackBehavior();
      }

    }

    private void AttackBehavior()
    {
      transform.LookAt(target.transform);
      if (timeSinceLastAttack > weapon.GetTimeBetweenAttack())
      {
        TriggerAttack();
        timeSinceLastAttack = Mathf.Infinity;

      }
    }

    private void TriggerAttack()
    {
      GetComponent<Animator>().ResetTrigger("stopAttack");//This will trigger HIT() event
      GetComponent<Animator>().SetTrigger("attack");
    }

    void Hit()
    {
      if (target == null)
      {
        return;
      }
      if (currentWeapon.HasProjectile())
      {
        currentWeapon.LaunchProjectile(rightHandTransform, leftHandTransform, target);
      }
      else
      {
        target.TakeDamage(currentWeapon.GetDamage());
      }

    }
//adding code
    void Shoot()
    {
      Hit();
    }
    public void EquipWeapon(weapon weapon)
    {
      currentWeapon = weapon;
      Animator animator = GetComponent<Animator>();
      weapon.Spawn(rightHandTransform, leftHandTransform, animator);
    }

    private bool GetIsInRange()
    {
      return Vector3.Distance(transform.position, target.transform.position) < currentWeapon.GetRange();
    }

    public void Attack(GameObject combatTarget)
    {
      GetComponent<ActionScheduler>().StartAction(this);
       //Might be the magic ticket!
      target = combatTarget.GetComponent<Health>();

    }

    public void Cancel()
    {
      
      TriggerStopAttack();
      target = null;
      GetComponent<Mover>().Cancel();
    }

    private void TriggerStopAttack()
    {
      GetComponent<Animator>().ResetTrigger("attack");
      GetComponent<Animator>().SetTrigger("stopAttack");
    }


    public bool CanAttack(GameObject combatTarget)
    {
      if (combatTarget == null)
      {
        return false;
      }
      Health targetToTest = combatTarget.GetComponent<Health>();
      return targetToTest != null && !targetToTest.IsDead();
    }
    //ANIMATION EVENT

  }
}

I might need to look at Damage Pop up and put some logic in there if the Enemy IsDead == True, don’t show the floating damage…

If you have any better ideas let me know!

Thanks!

This might help a little as well.

using System.Collections.Generic;
using UnityEngine;
using RPG.Core;


namespace RPG.UI.DamageText
{
  public class DamageTextSpawner : MonoBehaviour
  {
    //Component that is in the root of the prefab
    [SerializeField] DamageText damageTextPrefab = null;


    public void Spawn(float damageAmount)

    {

      {
        DamageText instance = Instantiate<DamageText>(damageTextPrefab, transform);
        instance.setValue(damageAmount);
      }
    }

  }
}

This might help a little more. I am trying to figure out how to bring over the bool of IsDead over here and only instantiate the damage text if isDead is false.

Check in Hit() to see if your target is still alive as well (after the null)
The reason Hit() can still fire is that animation transitions blend… so if the attack already started, then during the transition back to Locomotion, the Hit() can fire if it hasn’t fullly transitioned to the Locomotion state.
So in Hit, change the first if statement:

if(target==null  || target.IsDead()) return;

For avoiding showing overkill (damage done after the body is dead), in Health’s TakeDamage, make the first line:

if(IsDead()) return;

That worked! Thank you so much!

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

Privacy & Terms