• 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
0
Question by Slaifir · Apr 25, 2015 at 09:50 PM · crashrandomgenerationtower-defenseoverload

Unity crashes with my function for random generating paths

Hello, this is my first time posting here.

Right now, I'm working on a tower defense game, but I wanted to give it a special touch by making the "map" randomly generated. The problem is that one of my functions is crashing Unity and I don't know why.

The basic idea of the game is a 18x18 board, where the borders enclose a 16x16 board inside. The player is at (1, 1) and the enemies spawn at (16, 16). To make the path randomly generated, at the beginning the board is first filled with blocks, and then a function is called to destroy some of those walls to make a path between the enemy spawn and the player zone.

To generate this way, that function calls another function, which keeps track of an imaginary point and chooses a random direction. If that direction isn't the one where it came from and doesn't have one of the outer walls blocking it, then it stores the resulting coordinate into an array. After the imaginary point eventually reaches the player zone, the function returns the array it created.

This last function crashes the game each time it is called. Here it is:

 Vector3[] RandomWay()
     {
         int d;
         int a = 0;
         Vector3[] path = new Vector3[256];
         int count = 1;
         path[count - 1] = new Vector3(16, 16, 0);
         Vector3 pastPosition;
 
         while (path[count] != new Vector3(1, 1, 0))
         {
             pastPosition = path[count - 1];
 
             while (a != 1)
             {
                 d = Random.Range(0, 3);
 
                 if (d == 0)
                 {
                     if (checkMovement(path[count], pastPosition, 0, 1) == true)
                     {
                         //If there isn't a wall up and the tracking didn't come from there then...
                         //Up
                         path[count] = new Vector3(path[count].x, path[count].y + 1, 0);
                         break;
                     }
                 }
                 else if (d == 1)
                 {
                     //Right
                     if (checkMovement(path[count], pastPosition, 1, 0) == true)
                     {
                         path[count] = new Vector3(path[count].x + 1, path[count].y, 0);
                         break;
                     }
                 }
                 else if (d == 2)
                 {
                     //Down
                     if (checkMovement(path[count], pastPosition, 0, -1) == true)
                     {
                         path[count] = new Vector3(path[count].x, path[count].y - 1, 0);
                         break;
                     }
                 }
                 else if (d == 3)
                 {
                     //Left
                     if (checkMovement(path[count], pastPosition, -1, 0) == true)
                     {
                         path[count] = new Vector3(path[count].x, path[count].y - 1, 0);
                         break;
                     }
                 }
             }
             count += 1;
         }

I thought at first that there may be an infinite loop somewhere, but I couldn't find it. There's probably a better way to do this, but I'm still an amateur in all this. What's wrong with my function?

Comment
Add comment · Show 1
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 AlwaysSunny · Apr 25, 2015 at 09:50 PM 0
Share

It's very easy to create an infinite loop with a while() loop if you're not able to guarantee the satisfaction of the condition that terminates the loop.

I see no "insurance policy" here to assure these while-loops will terminate. An infinite loop is one of the only things that will cause unity to hang, so if it hangs, there's a good chance that's what's going on.

It is "illegal" in programming to create loop which has a chance to execute forever; how to provide termination insurance varies case by case, and isn't something I'd expect help with in any complex system (which is any system like this one which cannot be instantly understood by another reader).

2 Replies

· Add your reply
  • Sort: 
avatar image
0

Answer by Addyarb · Apr 25, 2015 at 10:09 PM

Here's a script I wrote for you! This is using an actual cube gameObject to go through and use collision to delete the other grid cubes. To use this script...

  1. Tag your grid objects as "Cube".

  2. make a cube the same size as your grid cubes, and add a collider onto it.

  3. make the collider a trigger collider.

  4. set the grid width to whatever it may be(sounds like 8x8 in your case?).

  5. Let the cube do the work!

      bool finished;
         int forwardCount;
         int rightCount;
         public int widthOfGrid;
         public int lengthOfGrid;
    
         void Update () {
         if (!finished){
                 MoveRandomDirection();
             }
         if (rightCount == 5 && forwardCount == 5) {
                 finished = true;
                 Destroy (gameObject,1);
             }
         }
     
         void MoveRandomDirection(){
             int randomInt = Random.Range (0, 3);
             if (randomInt == 1 && rightCount < widthOfGrid) {
                 transform.Translate (Vector3.right);
                 rightCount++;
             } else {
                 if(randomInt == 2 && forwardCount < lengthOfGrid){
                     transform.Translate(Vector3.forward);
                     forwardCount++;
                 }
             }
         }
     
         void OnTriggerEnter(Collider col){
             if (col.gameObject.tag == "Cube") {
                 Destroy (col.gameObject);
             }
         }
    
    

As AlwaysSunny mentioned, you really have to know what you're doing before you try a while loop (especially in Unity). My suggestion would be to instead use an if block and put all of this in the update function (or call it in the update function for simplicity).

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 Slaifir · Apr 25, 2015 at 11:56 PM 0
Share

I don't know if that's a good idea. The board needs to be generated at the beginning of the game.

I checked, and indeed, the problem is inside the second while loop, but I don't know what's causing it. I have tried to add an "else break" at the end to see if the problem is still there but I can't find nothing.

avatar image Addyarb · Apr 26, 2015 at 12:01 AM 0
Share

I have created something (relatively) similar for tree spawning. At first I was using while loops, but after countless hours trying to track down why the while loop kept crashing Unity, I switched to the Update method.

$$anonymous$$y approach was to handle it all, and then disable the script. However, you can just use a bool to effectively set the script inactive until you want to regenerate a new map if you'd prefer.

I've used while loops elsewhere in code with no problem, but for Unity I tend to shy away because it essentially just crashes the game with (as you stated) no inkling as to what might be causing it.

avatar image Slaifir · Apr 26, 2015 at 12:04 AM 0
Share

Hmmm I see. I'll try that then to see if it works

avatar image Addyarb · Apr 26, 2015 at 12:51 AM 0
Share

Answer updated with a script I wrote. Works great for me, let me know if it has any issues and I'll try to help.

Good luck!

avatar image Slaifir · Apr 26, 2015 at 02:50 AM 0
Share

Thank you really much! I will try it later

avatar image
0

Answer by Slaifir · Apr 26, 2015 at 11:38 AM

By the way, here is the checkMovement function that makes sure the "point" is not going outside of the borders or in the direction it came from.

     bool checkMovement(Vector3 currentPos, Vector3 pastPos, int xChange, int yChange)
     {
         //Makes a temporary variable to keep track of what the new coordinates would be
         Vector3 temp = new Vector3(currentPos.x + xChange, currentPos.y + yChange, 0);
 
         //If the direction is the same one where the "point" was, it tells the caller that it shouldn't go in that direction
         if (temp == pastPos)
         {
             return false;
         }
 
         //If the new coordinates are gonna be one of the borders, this tells the caller to not do that movement
         if ((temp.x - xPosition) > 16 || (temp.y - yPosition) > 16 || (temp.x - xPosition) < 1 || (temp.y - yPosition) < 1)
                 return false;
 
         //If nothing of that is gonna happen, then the movement can be executed
         return true;
     }
Comment
Add comment · 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

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

Randomly generated/ procedurally generated world 1 Answer

Randomly Generated Objects inside an area 3 Answers

Attempt at re-arranging list results in crash 1 Answer

What is a good way to randomly generate clouds along a path? 0 Answers

How to get neighbor from for loop in hexagonal grid ? 2 Answers

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