[Solved]Cant Find loop that freezes Unity
Hi! I'm currently working on a school project. I'm trying to make a random map generator that spawns bricks on the map random every time you start the level, nothing special just spawns random blocks or empty places. this codes is the only code that is in the game and as fast as i start Unity it freezes so i thought i was an infinite loop. I have only 2 while loops in the code witch i believe to be the problem but no matter what i do i cant break the loop or debug it. So I'm wondering if someone can help me with what I'm doing wrong, there must be some problem I'm not seeing.
Here is the code int the script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CreateMap : MonoBehaviour {
public int xRows;
public int yRows;
public int emptySpacesTotal;
public float xPosStart;
public float yPosStart;
public GameObject[] Bricks;
public int[] brickToCreate;
public int xSpacingMultiplyer = 2;
public int ySpacingMultiplyer = 1;
private int[] brickCheck;
private int emptySpacesCount = 0;
private int blockCount = 0;
private Transform Map;
private List<Vector3> gridPos = new List<Vector3>();
void Awake () {
/*Make sure that you cant set different sizes on game object array and int array*/
if (Bricks.Length != brickToCreate.Length) {
Debug.LogError (string.Format ("Size of {0} array needs to be equal to size of {1} array! Called from (game object and (script)) {2} ", Bricks.ToString (), brickToCreate.ToString (), GetComponent<MonoBehaviour> ().ToString ()));
Debug.Break();
} else {
/*create editble private copy of array*/
brickCheck = brickToCreate;
}
/*make sure that x and y dont over/under-extend the gameboard*/
xRows = Mathf.Clamp (xRows, 1, 17);
yRows = Mathf.Clamp (yRows, 1, 18);
/*make sure that it cant be more empty spaces then half of the rows created*/
if (emptySpacesTotal > Mathf.RoundToInt((yRows * xRows) / 2)) {
emptySpacesTotal = Mathf.RoundToInt((yRows * xRows) / 2);
}
/*get parent*/
Map = GameObject.FindGameObjectWithTag("GameController").transform;
}
private void InizializeGridPos(){
for (int x = 0; x < xRows; x++) {
for (int y = 0; y < yRows; y++) {
gridPos.Add (new Vector3 ( Map.position.x + (xPosStart + x * xSpacingMultiplyer),
Map.position.y - (yPosStart + y * ySpacingMultiplyer), 0.0f));
}
}
}
private int RandomNumber(int min, int max){
int randomNumber = Random.Range (min, min);
return randomNumber;
}
private void SubtractCreatedBrick(int pos){
if (brickCheck[pos] > 0) {
brickCheck[pos] = brickCheck[pos] - 1;
blockCount++;
}
}
private bool IsPosZero(int pos){
if (brickCheck[pos] == 0) {
return true;
} else {
return false;
}
}
private bool ArrayIsNotEmpty(){
int BrickTypeIsZero = 0;
for (int i = 0; i < brickCheck.Length; i++) {
if (brickCheck[i] == 0) {
BrickTypeIsZero++;
}
}
if (BrickTypeIsZero < brickCheck.Length - 1) {
return true;
} else {
return false;
}
}
private Vector3 GetRandomPos(){
int randomPos = RandomNumber (0, gridPos.Count);
Vector3 pos = gridPos[randomPos];
gridPos.RemoveAt(randomPos);
return pos;
}
private GameObject GetBrickToSpawn(){
int randomBlock = RandomNumber (0, Bricks.Length);
if (ArrayIsNotEmpty ()) {
while (brickCheck[randomBlock] == 0) {
Debug.Log (string.Format ("brickChekc = {0}", brickCheck[randomBlock]));
Debug.Break();
randomBlock = RandomNumber (0, Bricks.Length);
}
SubtractCreatedBrick(randomBlock);
return Bricks [randomBlock];
} else {
return null;
}
}
private int Roll_50_50(){
int randomNumber = RandomNumber (0, 100);
if (randomNumber < 50) {
return 1;
} else {
return -1;
}
}
private void SpawnBricks(){
InizializeGridPos();
while(gridPos.Count > 0){
Debug.Log (string.Format ("gridCount = {0}", gridPos.Count));
Debug.Break ();
GameObject BrickToSpawn = GetBrickToSpawn();
if ( ((Roll_50_50 () == 1) && (emptySpacesCount < emptySpacesTotal)) || (BrickToSpawn == null) ) {
GetRandomPos();
emptySpacesCount++;
} else {
GameObject _instance = Instantiate (BrickToSpawn, GetRandomPos(), Quaternion.identity) as GameObject;
_instance.transform.SetParent(Map);
}
}
}
void Start(){
SpawnBricks();
}
}
Answer by hfiani · Nov 04, 2017 at 11:29 PM
this is one mistake, solve it and try to see:
int randomNumber = Random.Range (min, min);
it should be:
int randomNumber = Random.Range (min, max);
hahahhaha ofc... that was the problem... Tanks for the help, a second pair of eyes does so much sometimes!
Answer by MaxGuernseyIII · Nov 04, 2017 at 07:00 PM
If I were you, I would take out all the Debug.Break() calls and, instead, use the actual debugger.
Make Visual Studio your default editor.
Open one of your scripts, which will launch Visual Studio in a Unity-friendly way.
Attach to the unity editor.
Run your game.
Wait for it to freeze.
Hit the pause button in Visual Studio.
Odds are, you will land exactly in the offending loop but, if you don't, poke around the threads until you find the one that has the loop that is blocking Unity.
I tried what you suggested but i got the message "No compatible code running" an underneath it said "The selected debug engine does not support any code executing on the current therad (e.g. only native runtime code is executing)." so what am I'm suppose to do then ?
Like I said, you'll have to open up the threads window and start double-clicking on threads until you get to something with your code.
If none of the threads appear to be running your code, you're left with one of two possibilities:
It's your code that is causing the problem but it is not being built with the appropriate debugger symbols.
It's not your code that is causing the problem.
Since the latter leaves you kind of powerless, let's focus on the former for now. You have a couple avenues of recourse:
Ensure that you are attaching the right way. There is a specific menu option for attaching to Unity and I don't think debugging will work properly if you just use the regular "attach to process" feature. As far as I know, you have to have the Visual Studio Tools for Unity installed and you have to use them to attach.
Ensure that your code is being built in a debugger-friendly way. This means that it is either a free-floating script somewhere in your Assets folder (and therefore compiled by Unity) or a project building a .dll but that is generating a .mdb file to go with it. There is an obnoxious ritual you have to perform in order to get that second option. Basically, after your .dlls have been imported, you have open Visual Studio from the Unity Editor. I think you might only need to do it once but I like to do it once before each time I need the .mdbs to be accurate, since that's a pretty rare event in my life in the first place.
Go "around" the symbol table and just use the information you have available to you. If method names and class names are good enough, you might be able to right-click on the stack trace and uncheck something along the lines of "Show Only $$anonymous$$y Code". I don't know if this will work for Unity code but it works for ordinary .NET code, so it's worth a stab.
Your answer
Follow this Question
Related Questions
Why does this while loop freeze unity? 1 Answer
While loop freeze 0 Answers
While Loop Freezing Unity 1 Answer