Explosive Barrel

Hi !

I try to make an classic explosive barrel sytem : Barrel have 100HP, when the player shoot on him HP decrease when the barrel have 0 hp he explode and make damage at Enemy in the range of the explosion.

This is my script :

using UnityEngine;
using System.Collections;

public class ExplosiveBarrel : MonoBehaviour {

    public int startingHealth = 100;
    public int currentHealth;


    public float closeAreaEffect = 1.0F;
    public float mediumAreaEffect = 2.5F;


    public int closeDamage = 300;
    public int mediumDamage = 150;





    ParticleSystem hitParticles;
    ParticleSystem ExplodeParticles;
    public bool isExplodeDead;

    public Transform explosive;


    void Awake ()
    {

        ExplodeParticles = GetComponentInChildren <ParticleSystem> ();
        explosive = transform;
        currentHealth = startingHealth;
    }


    void Update ()
    {
     
     
    }

    public void TakeDamage (int amount)
    {
        if(isExplodeDead)
            return;



        currentHealth -= amount;

        //hitParticles.transform.position = hitPoint;
        //hitParticles.Play();

        if(currentHealth <= 0)
        {
            OnExplodeDeath ();
     
        }
    }


    void OnExplodeDeath ()
    {
        isExplodeDead = true;

 

    }
    void AreaDamageEnemies(Vector3 location, float radius, float damage)
    {
        if (isExplodeDead == true) {

            GameObject[] Enemy = GameObject.FindGameObjectsWithTag("Enemy");
            foreach ( GameObject other in Enemy) {

                float distance = Vector3.Distance (other.transform.position, explosive.position);
                EnemyHealth enemyHealth = other.GetComponent <EnemyHealth> ();
                if (distance <= closeAreaEffect) {
                    enemyHealth.TakeDamage (closeDamage);
                    Destroy (gameObject, 2f);
                } else if (distance <= mediumAreaEffect) {
                    enemyHealth.TakeDamage (mediumDamage);
                    Destroy (gameObject, 2f);
                }
            }
            /*Collider[] objectsInRange = Physics.OverlapSphere (location, radius);
            foreach (Collider col in objectsInRange) {

                float distance = Vector3.Distance (col.transform.position, explosive.position);
                EnemyHealth enemyHealth = col.GetComponent <EnemyHealth> ();
                if (distance <= closeAreaEffect) {
                    enemyHealth.TakeDamage (closeDamage);
                    Destroy (gameObject, 2f);
                } else if (distance <= mediumAreaEffect) {
                    enemyHealth.TakeDamage (mediumDamage);
                    Destroy (gameObject, 2f);
                }
            }*/
        }
    }

The HP System work, so when the player shoot on the barrel the HP Decrease, but when the barrel have 0 HP and explode, the enemy in the range didn’t take any damage, i try the physics way, because all my enemy have an collider, but same as the none physics way, they didn’t take any damage. I dont know what i should do for my barrel apply damage to my enemy :/.

Did you debug step by step?
Does it find Objects tagged as Enemy (Line 74)
Does the distance ever get smaller than close or mediumAreaEffect (79, 82).
If so, does the TakeDamageCall work as expected (80, 83)
What exactly are you trying to achieve by Line 81 and 84 (Destroy gets called for every enemy, and you are destroying the object that has the barrel script attached. That doesn’t make sense plus the barrel will remain if no damage is done…)

You are not calling AreaDamageEnemies function anywhere. Didn’t you forget to put the call to it in the TakeDamage function?

What do you mean ? I did the reverse, i call the EnemyHeatlh into the AreaDamage

I wrote an script when the Enemy capture an flag, the player loose and all enemies get kill, and that work, so i build this script with the same idea, when the barrel have 0 HP he call my void AreaDamage, kill on the enemy in the range. So :

using UnityEngine;
using System.Collections;

public class ExplosiveBarrel : MonoBehaviour {

    public int startingHealth = 100;
    public int currentHealth;


    public float closeAreaEffect = 1.0F;
    public float mediumAreaEffect = 5F;


    public int closeDamage = 300;
    public int mediumDamage = 150;

    public float power = 10f;   
    public float explosiveLift = 100f;




    ParticleSystem hitParticles;
    ParticleSystem ExplodeParticles; 
    public bool isExplodeDead;


    public Transform explosive;


    void Awake ()
    {

        ExplodeParticles = GetComponentInChildren <ParticleSystem> ();
        explosive = transform;
        currentHealth = startingHealth;
    }


    void Update ()
    {
       

    }

    public void TakeDamage (int amount)
    {
        if(isExplodeDead)
            return;



        currentHealth -= amount;

        //hitParticles.transform.position = hitPoint;
        //hitParticles.Play();

        if (currentHealth <= 0) {
            OnExplodeDeath ();
        }
    }


    void OnExplodeDeath ()
    {
       
        GameObject[] Enemy = GameObject.FindGameObjectsWithTag("Enemy"); // Look for all enemy on the map
        foreach ( GameObject other in Enemy) {

            float distance = Vector3.Distance (other.transform.position, explosive.position); // distance between Enemy & barrell
            EnemyHealth enemyHealth = other.GetComponent <EnemyHealth> (); // get Enemy heatlh
            if (distance <= closeAreaEffect) {  // close range or not ?
                enemyHealth.TakeDamage (closeDamage); // Apply the damage for close range
                Destroy (gameObject, 2f); // destroy barrel
            } else if (distance <= mediumAreaEffect) { // meduim range or not ?
                enemyHealth.TakeDamage (mediumDamage); // Apply damage for meduim range
                Destroy (gameObject, 2f); // destroy barrel
            }
        }

    }


   
}

And for the enemy script :

using UnityEngine;

public class EnemyHealth : MonoBehaviour
{
    public int startingHealth = 100;
    public int currentHealth;
    public float sinkSpeed = 2.5f;
    public int scoreValue = 10;
    public AudioClip deathClip;


    Animator anim;
    AudioSource enemyAudio;
    ParticleSystem hitParticles;
    CapsuleCollider capsuleCollider;
    ParticleSystem deathParticles; 
    bool isDead;
    bool isSinking;


    void Awake ()
    {
        anim = GetComponent <Animator> ();
        enemyAudio = GetComponent <AudioSource> ();
        deathParticles = GetComponentInChildren <ParticleSystem> ();
        capsuleCollider = GetComponent <CapsuleCollider> ();

        currentHealth = startingHealth;
    }


    void Update ()
    {
        if(isSinking)
        {
            transform.Translate (-Vector3.up * sinkSpeed * Time.deltaTime);
        }
    }


    public void TakeDamage (int amount)
    {
        if(isDead)
            return;

        enemyAudio.Play ();

        currentHealth -= amount;
           
        //hitParticles.transform.position = hitPoint;
        //hitParticles.Play();

        if(currentHealth <= 0)
        {
            Death ();
            //deathParticles.transform.position = deathPoint;
            deathParticles.Play();
        }
    }


    void Death ()
    {
        isDead = true;

       // capsuleCollider.isTrigger = true;

        anim.SetTrigger ("Dead");

        enemyAudio.clip = deathClip;
        enemyAudio.Play ();

        isSinking = true;

        GetComponent <NavMeshAgent> ().enabled = false;
        GetComponent <Rigidbody> ().isKinematic = true;
        ScoreManager.score += scoreValue;
                Destroy (gameObject, 3f);
    }


    public void StartSinking ()
    {
        isSinking = true;
         
    }
}

I think i understand what do you mean, i need to specify on my enemy what type of damage they can take, because on my script when i applied damage, he dont know to who take them … But i dont know how can i achieve that for the moment

Okay with that seem to be better :

using UnityEngine;
using System.Collections;

public class ExplosiveBarrel : MonoBehaviour {

    public int startingHealth = 100;
    public int currentHealth;


    public float closeAreaEffect = 1.0F;
    public float mediumAreaEffect = 5F;


    public int closeDamage = 300;
    public int mediumDamage = 150;

    public float power = 10f;
    public float explosiveLift = 100f;




    ParticleSystem hitParticles;
    ParticleSystem ExplodeParticles;
    public bool isExplodeDead;





    void Awake ()
    {

        ExplodeParticles = GetComponentInChildren <ParticleSystem> ();
        currentHealth = startingHealth;
    }


    void Update ()
    {


    }

    public void TakeDamage (int amount)
    {
        if(isExplodeDead)
            return;



        currentHealth -= amount;

        //hitParticles.transform.position = hitPoint;
        //hitParticles.Play();

        if (currentHealth <= 0) {
            OnExplodeDeath ();
        }
    }


    void OnExplodeDeath ()
    {

        isExplodeDead = true;
        Vector3 explosive = transform.position;
        Collider[] colliders = Physics.OverlapSphere (explosive, mediumAreaEffect);
        foreach (Collider hit in colliders) {
            Rigidbody rb = hit.GetComponent<Rigidbody> ();
            if (rb) {
                rb.AddExplosionForce (power, explosive, mediumAreaEffect, explosiveLift);
                //This is where we apply force to our enemy and various other rigid bodies
                hit.transform.root.GetComponentInChildren<EnemyHealth>().ExplosionDamage(mediumDamage);
                //This is where we apply damage to the enemy
                Destroy (gameObject);
            }

        }
    }


}

And for the health :

using UnityEngine;

public class EnemyHealth : MonoBehaviour
{
    public int startingHealth = 100;
    public int currentHealth;
    public float sinkSpeed = 2.5f;
    public int scoreValue = 10;
    public AudioClip deathClip;


    Animator anim;
    AudioSource enemyAudio;
    ParticleSystem hitParticles;
    CapsuleCollider capsuleCollider;
    ParticleSystem deathParticles;
    bool isDead;
    bool isSinking;


    void Awake ()
    {
        anim = GetComponent <Animator> ();
        enemyAudio = GetComponent <AudioSource> ();
        deathParticles = GetComponentInChildren <ParticleSystem> ();
        capsuleCollider = GetComponent <CapsuleCollider> ();

        currentHealth = startingHealth;
    }


    void Update ()
    {
        if(isSinking)
        {
            transform.Translate (-Vector3.up * sinkSpeed * Time.deltaTime);
        }
    }


    public void TakeDamage (int amount)
    {
        if(isDead)
            return;

        enemyAudio.Play ();

        currentHealth -= amount;
          
        //hitParticles.transform.position = hitPoint;
        //hitParticles.Play();

        if(currentHealth <= 0)
        {
            Death ();
            //deathParticles.transform.position = deathPoint;
            deathParticles.Play();
        }
    }
    public void ExplosionDamage (int amountExplosion)
    {
      
        currentHealth -= amountExplosion;

        if(currentHealth <= 0)
        {
            Death ();
            //deathParticles.transform.position = deathPoint;
            deathParticles.Play();
        }
    }


    void Death ()
    {
        isDead = true;

       // capsuleCollider.isTrigger = true;

        anim.SetTrigger ("Dead");

        enemyAudio.clip = deathClip;
        enemyAudio.Play ();

        isSinking = true;

        GetComponent <NavMeshAgent> ().enabled = false;
        GetComponent <Rigidbody> ().isKinematic = true;
        ScoreManager.score += scoreValue;
                Destroy (gameObject, 3f);
    }


    public void StartSinking ()
    {
        GetComponent <NavMeshAgent> ().enabled = false;
        GetComponent <Rigidbody> ().isKinematic = true;
        isSinking = true;
          ScoreManager.score += scoreValue;
        Destroy (gameObject, 3f);
    }
}

But i have an error when the barrel explode and apply damage to enemy ( BUT THAT WORK AND KILL THE ENEMY AND DESTROY THE BARREL AFTER ) :

NullReferenceException: Object reference not set to an instance of an object
ExplosiveBarrel.OnExplodeDeath () (at Assets/Scripts/ExplosiveBarrel.cs:72)
ExplosiveBarrel.TakeDamage (Int32 amount) (at Assets/Scripts/ExplosiveBarrel.cs:58)

Anyone for help fix that ?

Yeah but do you use 2 scripts or one