• Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
2
Question by Afoo · Aug 31, 2014 at 06:23 PM · c#freeze

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.

Comment
Add comment · Show 2
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Afoo · Sep 03, 2014 at 05:18 PM 0
Share

Seems I had some terrible wrong logic behind direction select. Sorry for your time.

avatar image kacyesp · Sep 03, 2014 at 06:06 PM 1
Share

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.

2 Replies

· Add your reply
  • Sort: 
avatar image
0

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.

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Afoo · Sep 01, 2014 at 04:15 AM 0
Share

Thanks, will look for these changes when I come back from work today.

avatar image
2

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.

Comment
Add comment · Show 5 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Kiwasi · Sep 01, 2014 at 12:33 AM 1
Share

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.

avatar image kacyesp · Sep 01, 2014 at 12:55 AM 1
Share

@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" :)

avatar image Afoo · Sep 01, 2014 at 04:21 AM 0
Share

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.

avatar image Kiwasi · Sep 01, 2014 at 06:04 AM 1
Share

@Afoo It doesn't really matter if you see the infinite loop or not. Unity can see it.

avatar image Kiwasi · Sep 01, 2014 at 06:14 AM 1
Share
 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 terminate. $$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.

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Welcome to Unity Answers

The best place to ask and answer questions about development with Unity.

To help users navigate the site we have posted a site navigation guide.

If you are a new user to Unity Answers, check out our FAQ for more information.

Make sure to check out our Knowledge Base for commonly asked Unity questions.

If you are a moderator, see our Moderator Guidelines page.

We are making improvements to UA, see the list of changes.



Follow this Question

Answers Answers and Comments

4 People are following this question.

avatar image avatar image avatar image avatar image

Related Questions

Inspector vs Script: Component best practice? 1 Answer

Inventory system using an array... 3 Answers

Multiple Cars not working 1 Answer

Player movement issue... 1 Answer

Unity Freeze When Applying my Script to GameObject 3 Answers

  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges