- Home /
Enemies do damage even after dying
When shot, enemy object disappears.. But the damage is continuously going until the player dies. Here are the scripts used on the enemy.
void FixedUpdate () {
transform.LookAt (player.transform);
if (Physics.Raycast (transform.position, transform.TransformDirection (Vector3.forward), out shot)) {
targetDistance = shot.distance;
if (targetDistance < allowedRange) {
enemySpeed = 0.6f;
if (attackTrigger == 0) {
enemy.GetComponent<Animation> ().Play ("Walking");
GetComponent<Rigidbody>().AddForce(transform.forward * enemySpeed * Time.deltaTime);
}
} else {
enemySpeed = 0;
enemy.GetComponent<Animation> ().Play ("Idle");
}
}
if (attackTrigger == 1) {
if (isAttacking == 0) {
StartCoroutine(EnemyDamage());
}
enemySpeed = 0;
enemy.GetComponent<Animation>().Play("Attacking");
}
}
void OnTriggerEnter() {
attackTrigger = 1;
}
void OnTriggerExit() {
attackTrigger = 0;
}
IEnumerator EnemyDamage() {
isAttacking = 1;
painSound = Random.Range (1, 4);
yield return new WaitForSeconds (0.9f);
screenFlash.SetActive (true);
GlobalHealth.playerHealth -= 10;
if (painSound == 1) {
hurt01.Play ();
}
if (painSound == 2) {
hurt02.Play ();
}
if (painSound == 3) {
hurt03.Play ();
}
yield return new WaitForSeconds (0.05f);
screenFlash.SetActive (false);
yield return new WaitForSeconds (1);
isAttacking = 0;
}
Second one which is responsible for enemy death.
void Update () {
if (enemyHealth <= 0) {
this.GetComponent<ZombieFollow>().enabled = false;
zombie.GetComponent<Animation>().Play("Dying");
StartCoroutine(EndZombie());
}
}
void DeductPoints(int damageAmount) {
enemyHealth -= damageAmount;
}
IEnumerator EndZombie() {
yield return new WaitForSeconds(3);
Destroy(gameObject);
}
You must stop the EnemyDamage() coroutine in the first script, from the Update() of the second script, just after the enemy dies.
To do this, the second script must have access to the first, and the first script must also provide a public method, which will be called by the second script, and which will call StopCoroutine:
https://docs.unity3d.com/ScriptReference/$$anonymous$$onoBehaviour.StopCoroutine.html
In the update function of the second script, I already disabling the first script. Isn't it enough?
Yes, it looks like it's enough, provided the coroutine is killed immediately as the enabled property is set. Anyway, I would prefer stopping the coroutine directly, rather than rely on the enabled property.
I couldn't know that the ZombieFollow
component refers to the first script, because you haven't provided such info.
Answer by Jordash · Nov 04, 2018 at 04:11 PM
A lot of your code seems to be overkill for what you're trying to achieve, so my first piece of advice is to reorganise it. Bugs like this can easily spring up when using much more complicated systems than needed. Think about what you're trying to achieve overall and consider whether there is a simpler way to do something.
Your bug is likely caused by something funky in the coroutine, maybe because isAttacking = 1 is inside there is a slight delay before it is called, you should put it in the method calling the coroutine to be safe. A quick fix and generally good practice would be to do a check inside the coroutine whether the zombie is still alive before allocating the damage.
And just some tips for your code. From the looks of it you want your enemy to walk towards the player check when an they are close enough and to swipe with delayed damage.
Your code for detecting distance need only be a Vector3.Distance check, a raycast is unnecessary for every frame. (Depending on whether something might interrupt the ray, you can bring one back later but I'd generally do a distance check first).
The damage from the swipe can stay in a coroutine but get rid of everything that isn't delayed. Once you're in the coroutine you can check whether the zombie is still alive and whether the attack will hit the player, what if they backed off in the 0.9 seconds since the attack started? Also move the code which damages the player to the player object, it logically should go there and helps if anyone else is ever looking at your code.
For the zombie damage code checking in the update for death is necessary, as you already have a public function to reduce health you can do the check in that function. The beauty of private and public functions is you can be certain that any other script must go through that function to affect the zombie's health so the death check will always happen.