We want the spawner to spawn for the duration of the game, but it will stop spawning about half though the level. Their are also unspawned groups in our object pool that never get spawned. Also we just updated unity to 5.2 when this started happening.
(Note: the objects highlighted in blue are the intended objects to be spawned by this specific spawner).
Spawner Script:
using UnityEngine;
using System.Collections;
public class SqiushySpawner : MonoBehaviour {
public GameObject[] nets;
public float minTime = 10.0f;
public float maxTime = 25.0f;
private int curNet = 0;
void Start(){
Invoke("Spawn", Random.Range(minTime,maxTime));
}
void Spawn(){
//just copied your code here
GameObject obj = NewObjectPool.instance.GetObjectForType (nets[curNet].name, true); // had "NetOfDeathV3 3" .. also assuming the prefabs have the correct names
if (obj == null)
return;
obj.transform.position = transform.position;
obj.transform.rotation = transform.rotation;
obj.SetActive (true);
curNet = Random.Range(0,12);
if(curNet > nets.Length){
curNet = 0;
}
Invoke("Spawn", Random.Range(minTime,maxTime));
}
}
I imagine that you could just use a coroutine for that.
using UnityEngine;
using System.Collections;
public class SqiushySpawner : MonoBehaviour
{
public GameObject[] nets;
public float minTime = 10f;
public float maxTime = 25f;
private int curNet = 0;
IEnumerator Start()
{
while(true)
{
yield return new WaitForSeconds(Random.Range(minTime, maxTime));
GameObject obj = NewObjectPool.instance.GetObjectForType (nets[curNet].name, true);
if (obj != null)
{
obj.transform.position = transform.position;
obj.transform.rotation = transform.rotation;
obj.SetActive (true);
curNet = Random.Range(0,12);
if(curNet > nets.Length)
{
curNet = 0;
}
}
}
}
}
The above code should just wait, run, repeat forever. I, personally, also think it makes the intent of the code a bit more clear when itâs written this way. I hope that helps.
Thanks for the help, sadly though when tested only one group was spawned during the duration of the level.
Iâm wondering why only one group? Perplexing.
Your own code sample will stop spawning as soon as null is returned by âNewObjectPool.instance.GetObjectForTypeâ. Noone except you knows under which circumstances ânullâ will be returned.
The coroutine example does a little better, it doesnât stop trying to spawn yet the problem still exists, as it wonât continue to execute the content of the if statement as soon as you will get an index that makes âNewObjectPool.instance.GetObjectForTypeâ return null.
The apparent reason:
The only chance (according to your code) to generate a new index is when the current index does not lead to a return value of ânullâ.
In other words, once null is returned, the index stays the same and the method will most-likely keep returning null for that index unless thereâs another control outside of that script.
Thanks the advice it put us a step closer to solving this. The spawner did spawn for a longer amout of time until an error came into the console, then it stopped spawning:
Updated version of the spawner:
using UnityEngine;
using System.Collections;
public class SqiushySpawner : MonoBehaviour {
public GameObject[] nets;
public float minTime = 10.0f;
public float maxTime = 25.0f;
private int curNet = 0;
void Start(){
Invoke("Spawn", Random.Range(minTime,maxTime));
}
void Spawn(){
//just copied your code here
GameObject obj = NewObjectPool.instance.GetObjectForType (nets[curNet].name, true); // had "NetOfDeathV3 3" .. also assuming the prefabs have the correct names
if (obj == null)
Invoke("Spawn", Random.Range(minTime,maxTime));
obj.transform.position = transform.position;
obj.transform.rotation = transform.rotation;
obj.SetActive (true);
curNet = Random.Range(0, nets.Length);
Invoke("Spawn", Random.Range(minTime,maxTime));
}
}
I didnât have anything specific in mind, that was just an addition to how this could be avoided.
You could also just put the integer generating part outside of the null check so that it generates a new one all the time even though the current one made the method return null.
However, If you need to stick with that specific index and do not simply want to generate a new one, youâll need to make sure that the pool object is ready again.
Thanks, we finally got the spawner to kept generating infinitely. However now we have run into another problem with the spawner. The Gameobjects need a delay between each spawn so they donât spawn on top of each other. We just want one or two on screen at a time.
Current spawner code:
using UnityEngine;
using System.Collections;
public class SqiushySpawner : MonoBehaviour {
public GameObject[] nets;
public float minTime = 10f;
public float maxTime = 25f;
private int curNet = 0;
void Awake ()
{
Invoke ("WillStartSpawn", 35f);
//Debug.Log ("Spawner will start in ....");
}
void WillStartSpawn ()
{
StartCoroutine (Start ());
//Debug.Log ("Spawning has started");
}
IEnumerator Start()
{
while(true)
{
yield return new WaitForSeconds(Random.Range(minTime, maxTime));
GameObject obj = NewObjectPool.instance.GetObjectForType (nets[curNet].name, true);
//Debug.Log("Squishy is spawned");
if (obj != null)
{
obj.transform.position = transform.position;
obj.transform.rotation = transform.rotation;
obj.SetActive (true);
curNet = Random.Range(0, nets.Length);
StartCoroutine(ResetSpawn());
}
}
}
IEnumerator ResetSpawn ()
{
//Debug.Log ("Spawn will reset");
yield return new WaitForSeconds(15f);
StartCoroutine (Start ());
//Debug.Log ("Spawn is reset");
}
}
The start coroutine will continue running even though you start the reset coroutine. Youâll actually start more and more coroutines (the first one) and they will all keep running because youâre using while(true).
Thanks, but I solved the overlapping problem by changing the min and max time on the spawner (kind of stupid that I didnât do that before). but, since I solved the issue should I still worry about ?
Well, in theory (again depending on the circumstances under which the pool method returns null) you could eventually have tens or hundreds or potentially thousands of those coroutines running. I doubt that would happen, there will be a situation in which many of them cannot find an index for a pool object which is ready and thus wonât pass the null check, but anyway.
Even if that wasnât a visual problem, itâs still unnecessary to have all those coroutines running in the background and if you play long enough that may even be noticeable (probably, but never tried it).
If you intend to only continue the Start coroutine after ResetSpawn has finished, then just remove the loop. The coroutines will still call each other like: Start calls ResetSpawn and ends, ResetSpawn calls Start and ends, Start calls ResetSpawn âŚ
At the moment (disregarding that the objects in the pool may all be in use and null is returned by the pool method) it works more like: Start calls ResetSpawn and startes all over again due to the loop⌠ResetSpawn starts another one of the Start coroutine, you now have 2 of them running and both will start a Reset Coroutine. These both reset coroutines will each start a new Start coroutine, you now have 4 of them running, which will start 4 Reset coroutines⌠in theory thereâs a risk of an exponential increase.