Unity freezes. I dont know why...
Hello community :D
I have a really big problem here since it totally prevents me from working on my game...
Here it is:
I have a game that spawnes enemys when i press Enter. All the scripts used for this are these:
The GameManager controlls how many rounds have passed and checks if i press Enter:
public static int rounds = 1;
public static bool roundIsRunning = false;
void Update () {
if (roundIsRunning == false && Input.GetKeyDown (KeyCode.Return)) {
Debug.Log("Round startet");
Debug.Log("This is round " + rounds);
rounds++;
roundIsRunning = true;
EnemySpawner.activeSpawner.spawnEnemy(rounds);
}
}
The EnemysSpawner spawns all the enemys when called:
private bool spawnNext = true;
public Transform defSpawn;
public GameObject enemyPrefab;
public float maxOffset;
public float spawnRate;
public int remaining = 0;
public int enemysOnField = 0;
public static EnemySpawner activeSpawner;
void Awake() {
//Creating a static instance to be called form other scripts
if (activeSpawner == null)
activeSpawner = this;
else if (activeSpawner != this)
Destroy (gameObject);
}
public void spawnEnemy(int rounds){
//Loop variable to Debug.Log how many loops have passed
int loop = 0;
Debug.Log("Enemys spawning...");
//Remaining is the count of enemys based on the round you are in
remaining = (int)Mathf.Log (rounds, 2f);
Debug.Log ("Total enemys: " + remaining);
//Spawning all the enemys in this loop
while (remaining > 0) {
loop++;
if (spawnNext == true) {
Instantiate (enemyPrefab, getSpawnPos(), Quaternion.identity);
remaining--;
Debug.Log("Spawned an enemy. Remaining:" + remaining);
enemysOnField++;
spawnNext = false;
//Starting a coroutine so that there is a little time in between spawns
StartCoroutine(waitForNextEnemy());
}
Debug.Log("Looped " + loop + " times");
}
Debug.Log ("All enemys spawned");
GameManager.roundIsRunning = false;
Debug.Log ("Round is over");
}
public Vector3 getSpawnPos(){
Vector3 spawnPos = defSpawn.position;
spawnPos.y += Random.Range (-maxOffset, maxOffset);
return spawnPos;
}
IEnumerator waitForNextEnemy() {
Debug.Log ("Waiting till next spawn...");
yield return new WaitForSeconds (0.5f);
spawnNext = true;
}
I beg you to read through this and tell me what is wrong. I have already had some problems with coroutines but i dont know how this could be an issue here...
Also I should mention that it only freezes on the 3rd time I press Enter. The first 2 times it works perfectly fine.
In addition it freezes while still in the GameManager script. I can tell because it wont even show the first Debug.Log message. It freezes before that :/
I hope you guys can help me because this is starting to piss me off :(
Thanks in advance :D
Answer by Dave-Carlile · Sep 25, 2015 at 06:03 PM
This code (with the non-important parts stripped out) is your problem...
while (remaining > 0) {
loop++;
if (spawnNext == true) {
remaining--;
spawnNext = false;
}
}
If remaining
is > 0 (or 1) this will cause an infinite loop. Either spawnNext
is false, in which case remaining
never gets decremented, or spawnNext
is true and it gets decremented once, after which spawnNext is changed to false and the loop will never end because remaining will never again be decremented.
Unity doesn't deal with infinite loops since everything runs on the same thread, so it hangs.
It looks like you want to spawn remaining
enemies with a pause between each. It would probably work best to make this entire thing a Coroutine. In your Update, change the call to this...
StartCoroutine(EnemySpawner.activeSpawner.spawnEnemy(rounds));
And change the header and loop in your spawnEnemy function...
public IEnumerator spawnEnemy(int rounds)
{
...
for (int i = 0; i < remaining; i++)
{
... instantiate the enemy and do your other stuff
yield return WaitForSeconds(0.5f);
}
...
}
Answer by hexagonius · Sep 25, 2015 at 06:15 PM
your while is causing an infinite loop as soon as remaining gets bigger than 1. it only gets the chance to reduce by one once, then it's stuck waiting for spawnNext to get true which it never does because that's happening in the coroutine which is not getting updated anymore because of the whole being stuck.
as a good rule of thumb use while only ever in a coroutine with at least one yield. this will prevent it from hanging the execution. in your case, you could move it into the coroutine and run your decrease, spawn, wait, decrease, spawn, wait... in there.
Answer by ComradeVanti · Sep 25, 2015 at 07:14 PM
Alright. Thanks people. I will change the code right away. Glad i can continue my game now :D Thanks alot :D
Your answer
Follow this Question
Related Questions
Unity freezes when script is run in play mode 2 Answers
How do I wait for input in a for loop. 0 Answers
How to stop infinite loop in Unity? 1 Answer
Can't think of a way to do this... 0 Answers