- Home /
Unity freezes on play
Hey, I'm starting to play with Unity, I want to rewrite a simple TD game I made in Java. Unfortunately very fast I bumped on a problem. When I click play my Unity freezes, I have to kill a task. I have no idea what's wrong, I tried some Debug.Logs but I can't even view them, can't access unity after the play button. I searched my code for infinite loops and I can't find any (being able to see console logs would help).
So far the code only has 3 classes, here's the first simple one to hold the static variables:
public class GlobalVariables : MonoBehaviour {
//The width of the board in blocks
public static int boardWidth = 40;
//The height of the board in blocks
public static int boardHeight = 36;
//The lenghth of the road in blocks;
public static int pathLength = 30;
//Pixel size of a block
public static int blockSize = 64;
void Start () {
}
void Update () {
}
}
Second class prepares a matrix, which I use for drawing:
public class MapCreator
{
//Array containing the path
int[] directionLayout = new int[GlobalVariables.pathLength];
public int[] getDirectionLayout ()
{
return directionLayout;
}
public MapCreator() {}
/**
*Returns an index layout of game board.
*/
public int[,] prepareMap ()
{
//X and Y position of start and end
int startValueX;
int startValueY;
//Used while creating a path
int tempValueX;
int tempValueY;
int xDirection;
int yDirection;
int pathRemaining = GlobalVariables.pathLength;
//Used for random
int[] randomDirection = {-1, 1};
//Return matrix
int[,] mapIndexLayout = new int[GlobalVariables.boardWidth, GlobalVariables.boardHeight];
for (int i = 0; i < GlobalVariables.boardWidth; i++) {
for (int k = 0; k < GlobalVariables.boardHeight; k++) {
mapIndexLayout [i, k] = 0;
Debug.Log("Filling with 0, step: " + i + ", " + k);
}
}
startValueX = Random.Range (1, GlobalVariables.boardWidth - 2);
startValueY = Random.Range (1, GlobalVariables.boardHeight - 2);
tempValueX = startValueX;
tempValueY = startValueY;
mapIndexLayout [startValueX, startValueY] = 2;
while (pathRemaining > 0) {
xDirection = randomDirection [Random.Range (0, 2)];
if (xDirection == 1) {
yDirection = -1;
} else {
yDirection = 1;
}
if (1 < (tempValueX + xDirection) && (tempValueX + xDirection) < (GlobalVariables.boardWidth - 2)
&& 1 < (tempValueY + yDirection) && (tempValueY + yDirection) < (GlobalVariables.boardHeight - 2)) {
if (mapIndexLayout [tempValueX + xDirection, tempValueY + yDirection] == 0) {
if (pathRemaining > 1) {
mapIndexLayout [tempValueX + xDirection, tempValueY + yDirection] = 1;
} else {
mapIndexLayout [tempValueX + xDirection, tempValueY + yDirection] = 3;
}
if (xDirection == 0 && yDirection == 1) {
directionLayout [40 - pathRemaining] = 8;
} else if (xDirection == 0 && yDirection == -1) {
directionLayout [40 - pathRemaining] = 2;
} else if (xDirection == 1 && yDirection == 0) {
directionLayout [40 - pathRemaining] = 6;
} else if (xDirection == -1 && yDirection == 0) {
directionLayout [40 - pathRemaining] = 4;
}
pathRemaining -= 1;
tempValueX += xDirection;
tempValueY += yDirection;
}
}
Debug.Log("Creating path, remains: " + pathRemaining + " blocks.");
}
Debug.Log("Path Created");
return mapIndexLayout;
}
// Use this for initialization
void Start ()
{
}
// Update is called once per frame
void Update ()
{
}
}
The last class takes the matrix and draws tiles based on it (well, it does not, but that's my goal :P)
public class MapDrawer : MonoBehaviour
{
//Object containing prepareMap method
MapCreator mapCreator = new MapCreator ();
//Textures has to be chosen in inspector
public Texture grassTexture;
public Texture roadTexture;
public Texture startTexture;
public Texture endTexture;
//Temporary texture
/**
* Method drawing a board
*/
void drawMap ()
{
Debug.Log("Begin drawing the map.");
//Index layout of game board
int[,] mapIndexLayout = mapCreator.prepareMap ();
//Temporary texture
Texture tempTexture;
if (!grassTexture && !roadTexture && !startTexture && !endTexture) {
Debug.LogError ("Assign Textures in the inspector.");
return;
}
for (int i = 0; i < GlobalVariables.boardWidth; i++) {
for (int k = 0; k < GlobalVariables.boardHeight; k++) {
tempTexture = setTextureById(mapIndexLayout[i, k]);
Debug.Log("Drawing at position: " + i + ", " + k);
GUI.DrawTexture (new Rect ((i * GlobalVariables.blockSize), (k * GlobalVariables.blockSize), GlobalVariables.blockSize, GlobalVariables.blockSize), tempTexture, ScaleMode.ScaleToFit, true, 0);
}
}
}
Texture setTextureById(int id) {
Debug.Log("Setting texture");
if (id == 0) {
return grassTexture;
} else if (id == 1) {
return roadTexture;
} else if (id == 2) {
return startTexture;
} else if (id == 3) {
return endTexture;
}
return null;
}
// Use this for initialization
void Start ()
{
drawMap ();
}
// Update is called once per frame
void Update ()
{
}
}
I would be grateful for any help. By the way, leaving the unity untouched doesn't help, but I noticed that memory usage keeps rising, slowly but steady, from ~~150000k to ~~700000k when I killed the task.
Seems I had some terrible wrong logic behind direction select. Sorry for your time.
So you did you have an infinite loop :) By the way, when people ask questions on here, they're supposed to vote up anything that helped them (answers or comments) and/or accept an answer if it answered their question.
Answer by kacyesp · Aug 31, 2014 at 10:30 PM
You have an infinite loop: while ( pathRemaining > 0 )
You only decrement pathRemaining when both of these if statements are true:
if (1 < (tempValueX + xDirection) && (tempValueX + xDirection) < (GlobalVariables.boardWidth - 2)
&& 1 < (tempValueY + yDirection) && (tempValueY + yDirection) < (GlobalVariables.boardHeight - 2)) {
if (mapIndexLayout [tempValueX + xDirection, tempValueY + yDirection] == 0)
Step through your code with a debugger or use Debug.Break() to pause the execution and see your Debug.Log statements in the console.
Pretty much the only time Unity freezes up is an infinite while loop. In every other case there will be an error.
One possible solution is to count iterations through your loop and abort if a set number is reached.
@Bored$$anonymous$$ormon I have 2 loops in my own code that were infinite in a few corner cases, and even after fixing them, I still leave a counter in there that breaks out after it hits 3 with a little comment saying "//Safety net" :)
Thanks for your help but I don't see an infinite loop there, the logic behind this if statement is: if tempValueX is in range from 1 to width -2, same for tempValueY, and then check if the Id on the matrix is 0 (which stands for grass, I fill the table with zeros in the begining). Even tho it might indeed take a long while I should, sooner or later, finish. I will look for Debug.Break() today when I come back from work.
@Afoo It doesn't really matter if you see the infinite loop or not. Unity can see it.
if (1 < (tempValueX + xDirection) && (tempValueX + xDirection) < (GlobalVariables.boardWidth - 2) && 1 < (tempValueY + yDirection) && (tempValueY + yDirection) < (GlobalVariables.boardHeight - 2)) {
if (mapIndexLayout [tempValueX + xDirection, tempValueY + yDirection] == 0) {
Both of these ugly if statements must return true for your loop to ter$$anonymous$$ate. $$anonymous$$y first suggestion would be to refractor these into something readable.
An alternative way to debug this would be to convert it into a coroutine, and yield return null immediately inside the while loop. Then you can watch the progress in real time.
Answer by AlwaysSunny · Aug 31, 2014 at 10:21 PM
Several things stand out:
GlobalVariables class doesn't need to inherit from MonoBehavior, and should be static.
GUI.DrawTexture, like any GUI.something call, must be called from built-in OnGUI(){} method.
GUI.DrawTexture is not a valid way to draw this many objects.
GUI.anything only works on the frame it was called, so calling outside a loop is generally useless.
Your best bet for creating a tile map is probably instantiating one quad per tile whose UVs match the desired texture on a texture atlas, then combining those quads into a single mesh to reduce draw calls from 100s to just 1.
Debug.Log lines can cause huge slowdowns. You should never have an instance where 100s of them can be made in the same frame. That might be your crash problem.
I didn't really dig into the code to look for specific errors beyond these, but these points need to be addressed.
Thanks, will look for these changes when I come back from work today.