chain of explosions - Destroying gameObjects in range

Hi there, I am having a little trouble with my code, I think its just due to the way I implemented my bomb system but when I try to create a chain of explosions.

The way I implemented it originally, was to get the destroyObjects method to call itself so that it would set of a chain reaction, I know know that this is definitely not a good way as unity just crashes out. I am guessing its causing an infinite loop or just feed-backing.

I deduced that if I am able to have “live” list management so that the list is populated and de-populated as objects go in and out of the range then I could use that but personally i am a little lost as how i would do that. Any and all suggestions are welcome.

`

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

//---------------------------------------------------------------------------------------
// NOTES & TO-DOs
//---------------------------------------------------------------------------------------
//
// Bombs do explode other bombs but currently only in the scope of the origional bomb
// i need to feed the bomb scope method to the currently exploding one so it searches for
// all of the bombs is scope
//---------------------------------------------------------------------------------------

public class Bomb : GameItem
{
	//static protected int bombBag = 100;
	
	// Bomblists ~ Stores all the Bombs
	public static List<GameObject> bombList = new List<GameObject>();
	
	// Movement & Force Vars
	const int noForce = 0;
	public int maxForce = 100;
	private int throwForce = 15;
	
	// Timer Vars
	private float bornTime;
	private int bombTime = 5;
	
	
	//-------------------------------------------------------------------------------------------------------------------------
	// Blast Radius and Collider Methods
	//-------------------------------------------------------------------------------------------------------------------------
	
	protected Collider [] radiusCollider;
	
	public static float radius = 3.0f;
	private SphereCollider radiusPreview;
	
	// Initialises the Radius Collider and links the collider to the 
	void INITRadius () {
		radiusCollider = Physics.OverlapSphere(transform.position, radius);
		radiusPreview = GetComponent("SphereCollider") as SphereCollider;
		radiusPreview.radius = radius;
	}
	
	public List<GameObject> inRadius () {
		
		List<GameObject> inRadiusList = new List<GameObject>();
		
		foreach (var collider in radiusCollider) {
			inRadiusList.Add((GameObject)collider.gameObject);
		}
		
		return inRadiusList;
	}
	//-------------------------------------------------------------------------------------------------------------------------
	// Bomb Detonation and Destruction Methods
	//-------------------------------------------------------------------------------------------------------------------------
	
	void bombTimer(){
		if((Time.time - bornTime) >= bombTime){
			INITRadius();
			DestroyObjects();
		}
	}
	
	void DestroyObjects () {
		foreach (var listItem in inRadius()) {
			if (listItem.tag != "NonDestructable" && listItem.tag != "Bomb") {
				Cube.destroyBlockWChk(listItem);
				Destroy(this.gameObject);
			}
			else if (listItem.tag != "NonDestructable" && listItem.tag == "Bomb"){
				expolde(listItem);
				Destroy(this.gameObject);
				
				//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
				// PUT EXPLODE OTHER BOMB METHOD HERE!
				//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
				
			}
			
		}
	}
	
	void expolde(GameObject target){
		Destroy(target.gameObject);		
	}

	void detonateOtherExplosives(){
		GameObject[] Bombs = GameObject.FindGameObjectsWithTag("Bomb");
		if(this.transform.position == Bombs[1].transform.position){
			Debug.Log("Booom!");
		}
	}
		
	//-------------------------------------------------------------------------------------------------------------------------
	// INIT
	//-------------------------------------------------------------------------------------------------------------------------

	void Start ()
	{
		// Iniialises the basclass GameItem()  ****************************** <- [ IMPORTANT FOR ALL CHILDREN OF GameItem ]
		base.INIT();
		
		//Add Bomb to the bombsArray
		bombList.Add(this.gameObject);
		
		// Grabs the time at instantiation of bombs
		bornTime = Time.time;
		
		//---------------------------------------------------------------------------------------
		// Controls Force [ ADD THIS TO ITS OWN METHOD WITH PARAMETERS ] ***********************
		//---------------------------------------------------------------------------------------

		
		// Adds an impulse on the first frame of creation which throws it in the direction of the Players aiming ray 
		this.rigidbody.AddForce(GameObject.FindGameObjectWithTag("AimDirection").transform.forward * throwForce, ForceMode.Impulse);
		
		// This was the old aiming system using [ up / down / left / right ]
		//this.rigidbody.AddForce(PlayerInteraction.rayDirection * throwForce, ForceMode.Impulse);
		
		// Puts new Bombs into the InstanceBin
		transform.transform.parent = GameObject.FindGameObjectWithTag("InstanceBin").transform;	
	}
	
	//-------------------------------------------------------------------------------------------------------------------------
	// UPDATE
	//-------------------------------------------------------------------------------------------------------------------------
	
	void Update ()
	{
		
		bombTimer();
		
	}	
	
	//-------------------------------------------------------------------------------------------------------------------------	 
	
}

`

This seems too complex for what you are trying to do. You are trying to do everything in one script that controls everything. This creates an overly complex, bloated script that is too easy to make a mistake and have it run on each object.

I would:

  • DO NOT try to get into data structures if you don’t need to. It’s too complex to deal with dynamic allocation for something like this.

  • DO NOT use GameObject.Destroy() on any object except this.gameObject, and only do that at the END of your explode function

  • When exploding, do the OverlapSphere like you already have, but instead of destroying each GameObject, use SendMessage to call a function on that object that causes it’s explosion. This is the safest, most versatile way to do this. It is easier to add onto a SendMessage setup that it is to add onto a Destroy setup. (make sure to use SendMessageOptions.DontRequireReciever)

  • Make sure that function returns without doing anything if it has already been called (prevents recursive loop)

  • I would personally wait a few frames during the explode function - this gives the engine a chance to actually handle the Destroy calls (they do not resolve until after the update cycle) and so that the player can get a bit of feedback on what is about to happen. It should also increase frame rate because you aren’t trying to do too many things in one frame and also the Destroy calls will make it so that there are fewer collides in the next frame, decreasing the overhead of the next OverlapSphere.