- Home /
How to object pool an Explosion
Hey soo i have 3 scripts, an object pooler script, a scipt that spawns a bomb at random location and a sticky bomb script. I want to make the explosion occur 5 seconds after spawning each the bomb prefab, however it only occurs once with the first prefab and the rest of the bombs do not explode. The error that comes up is: NullReferenceException: Object reference not set to an instance of an object StickyBomb.Explode () (at Assets/Worpman/Scripts/StickyBomb.cs:22)
Things to note: I have pooled both the sticky bomb and explosion prefab(the detonation prefab from Asset Store).| This is for a mobile game hence the reason why im doing this.| Sticky bomb is attach to the bomb prefab.| Spawn locations are just empty gameobjects at diffrent locations on the terrain.| A pooler gameobject has both the spawn script and object pooler script
STICKY BOMB SCRIPT;
using UnityEngine;
using System.Collections;
public class StickyBomb : MonoBehaviour {
// public GameObject explosionPrefab;
/* void OnCollisionEnter(Collision col)
{
this.GetComponent<Rigidbody>().isKinematic = true;
Invoke("Explode", 5);
} */
void Update()
{
Invoke("Explode", 5);
}
void Explode()
{
GameObject explosionPrefab = ObjectPooler.current.GetPooledObject("explosion");
// Instantiate(explosionPrefab, this.transform.position, this.transform.rotation);
explosionPrefab.transform.position = this.transform.position;
explosionPrefab.transform.rotation = this.transform.rotation;
explosionPrefab.SetActive(true);
gameObject.SetActive(false);
}
}
SCRIPT THAT SPAWNS THE BOMB
using UnityEngine;
using System.Collections;
public class SpawnBomb : MonoBehaviour {
public GameObject[] Spawner;
Transform bombpos;
public int SP_amount;
public float spawn_Wait; // Always changing
public float spawn_MostWait; // longest it will wait for
public float spawn_LeastWait; // least it would wait for
public int start_Wait; //time to first bomb being created
int randomPos;
public bool stop;
// Use this for initialization
void Start ()
{
StartCoroutine(waitBombSpawner());
}
// Update is called once per frame
void Update () {
spawn_Wait = Random.Range(spawn_LeastWait, spawn_MostWait); //minimum and maximum
}
void Awake()
{
//Spawner[randomPos].position = bombpos;
}
IEnumerator waitBombSpawner()
{
yield return new WaitForSeconds(start_Wait);
while (!stop)
{
randomPos = Random.Range(0, 6); // since its an array it picks a number between 0 and 5
GameObject BOMB = ObjectPooler.current.GetPooledObject("bomb"); // bomb from pooler
BOMB.transform.position = Spawner[randomPos].transform.position; //Picks a random location to be spawned
BOMB.SetActive(true); //put it back to active
yield return new WaitForSeconds(spawn_Wait);
}
}
}
OBJECT POOLER
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class ObjectPooler : MonoBehaviour {
public static ObjectPooler current;
[System.Serializable]
public class ObjectPoolItem
{
public GameObject pooledObject;
public int pooledAmount;
public bool WillGrow = true;
}
List<GameObject> pooledObjects;
public List<ObjectPoolItem> itemsToPool; // Newly added
// GameObject obj = ObjectPooler.current.GetPooledObject(); use it in another script to call this one
void Awake()
{
current = this;
}
void Start()
{
pooledObjects = new List<GameObject>();
foreach (ObjectPoolItem item in itemsToPool)
{
for (int i = 0; i < item.pooledAmount; i++)
{
GameObject obj = (GameObject)Instantiate(item.pooledObject);
obj.SetActive(false);
pooledObjects.Add(obj);
}
}
}
// void Update() { }
public GameObject GetPooledObject(string tag)
{
for (int i = 0; i<pooledObjects.Count; i++)
{
if (!pooledObjects[i].activeInHierarchy && pooledObjects[i].tag == tag)
{
return pooledObjects[i];
}
}
foreach (ObjectPoolItem item in itemsToPool)
{
if (item.pooledObject.tag == tag)
{
if (item.WillGrow) //Expands the pool
{
GameObject obj = (GameObject)Instantiate(item.pooledObject);
obj.SetActive(false);
pooledObjects.Add(obj);
return obj;
}
}
}
return null;
}
}
Answer by GrayMatterTutorials · Jan 09, 2017 at 08:08 AM
@OshakieGittens61, from the null reference error, it seems like it wasn't able to pull anything from the object pool. This could be because the Tag is misspelled. Likewise, you could have an error in the way you are spawning them where to many spawn at once. I would check if the returned object is null. Keep Debug.Logging it back until you find where it is coming up null. It should be when you are looking for the tag, and if that is the case, then you need to determine how to fix it at that point. It should work if you click will grow for the explosions. Are you ever setting those back to inactive??? But either way, I would just do some debug statements. If you still have errors, please upload a package to google drive or something and share the link.
Answer by UrielKane · Jan 09, 2017 at 09:31 AM
I suspect from what you said about "detonation prefab from asset store" that you are trying to use the classic detonator of asset store wich is free.
https://www.assetstore.unity3d.com/en/#!/content/1
If i'm correct. You are going have to modify the source code of the framework, becouse it destroy itself after make the detonation. Recently i was using it in my proyect but i have to remove it for two reasons. One is that the FXs are to expensive in runtime only one explosion on a prototype of scenario lvl and it suck/drop like 10/20 fps. So its not a good option when talking of optimization.
The second one was that i did not find an option for disable the destroy of the gameobject. In part that is becouse if im correct, the framework work by creating the particles at runtime insted of storing them on a prefab for reusability. So i could't pool them correctly. They are actualy created at runtime and destroyed, so no way to store them.
I end up remplacing them all with particle systems from both, legacy and shuriken. Storing them on prefab for pooling and so on. And for the physics i make my own explosion script, wich despawn after a certain time. I was learning this days that is better to just disable objects insted of destroying them. So i dont use destroy anymore. If i'm not pooling an object just desable them and move them far away from the action so the wont bother me in any way.
yh man, Everything you just mentioned is what I was going through. How did you make ur own explosion btw?