- Home /
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?
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 ter$$anonymous$$ates the loop.
I see no "insurance policy" here to assure these while-loops will ter$$anonymous$$ate. 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 program$$anonymous$$g to create loop which has a chance to execute forever; how to provide ter$$anonymous$$ation 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).
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...
Tag your grid objects as "Cube".
make a cube the same size as your grid cubes, and add a collider onto it.
make the collider a trigger collider.
set the grid width to whatever it may be(sounds like 8x8 in your case?).
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).
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.
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.
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!
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;
}
Your answer
![](https://koobas.hobune.stream/wayback/20220613193959im_/https://answers.unity.com/themes/thub/images/avi.jpg)