Problems with maze generator

Hi folks, I wrote a script in C# for generating a maze with prefabs, and i’ve been trying to convert it to Unityscript, and this is the 3rd re-write. When I run it, Unity locks up, so i’m guessing i’ve got a loop I can’t break out of but for the life of me I can’t find the problem anywhere. Anyone have any input? Here’s the script:

var dungeonFloor1 : GameObject;
var dungeonWall1 : GameObject;
var spacing = 4.0;
var pos;

var dungeonWidth = 128;
var dungeonHeight = 128;

var minRoomWidth = 2;
var minRoomHeight = 2;

var maxRoomWidth = 6;
var maxRoomHeight = 6;

var roomWidth = 3;
var roomHeight = 3;
var roomX = dungeonWidth / 2;
var roomY = dungeonHeight / 2;

var emptyDungeon = 0; //number to assign tile types in the array
var roomCorner = 1;
var northWall = 2;
var southWall = 3;
var eastWall = 4;
var westWall = 5;
var verticalDoor = 6;
var horizontalDoor = 7;
var roomFloor = 8;
var randomLoot = 9;

var halls = 0;
var rooms = 0;
var roomCount = 0;
var hallDirection = 0;
var wallDirection = "";
var roomDraw = true;
var doorX = 0;
var doorY = 0;
var roomStartTile = 0;
var maxRooms = 2;
var maxHalls = 2;

var gameDungeon = new int[dungeonWidth, dungeonHeight];				
								
																
function Start () {
	DrawRoomTilesToArray();
	GenerateRooms();
	OutputRoomTilesToScreen();
}




function DrawRoomTilesToArray() {
   	for (var tileCount = 0; tileCount < (roomWidth * roomHeight); tileCount++) {//loop until all tiles in room have been iterated
   		for (var y = 0; y < roomHeight; y++) {
        	for (var x = 0; x < roomWidth; x++) {
                gameDungeon[(roomX + x), (roomY + y)] = roomFloor; //mark floor tiles inside room
                gameDungeon[(roomX + x), (roomY - 1)] = northWall; //mark north wall tiles
                gameDungeon[(roomX + x), (roomY + roomHeight)] = southWall; //mark south wall tiles
                gameDungeon[(roomX + roomWidth), (roomY + y)] = eastWall; //mark east wall tiles
                gameDungeon[(roomX - 1), (roomY + y)] = westWall; //mark west wall tiles
			}
		}
	}
   	gameDungeon[roomX - 1, roomY - 1] = roomCorner; //mark northwest corner tile
    gameDungeon[roomX + roomWidth, roomY - 1] = roomCorner; //mark northeast corner tile
    gameDungeon[roomX - 1, roomY + roomHeight] = roomCorner; //mark southwest corner tile
    gameDungeon[roomX + roomWidth, roomY + roomHeight] = roomCorner; //mark southeast corner tile

	CountUpRooms();
}




function CountUpRooms() {
    if (roomWidth == 1 || roomHeight == 1)
        halls++;
    else
        rooms++;
    roomCount = rooms + halls; // step up room counter
}




function OutputRoomTilesToScreen() {
	for (var y = 0; y < dungeonHeight; y++) {
		for (var x = 0; x < dungeonWidth ; x++) {
			if (gameDungeon[x, y] > emptyDungeon  gameDungeon[x, y] < verticalDoor) {
            	pos = Vector3 (x, 1, y) * spacing;
            	Instantiate(dungeonWall1, pos, Quaternion.identity); }
            else if (gameDungeon[x, y] > westWall  gameDungeon[x, y] <= randomLoot) {
            	pos = Vector3 (x, 0, y) * spacing;
            	Instantiate(dungeonFloor1, pos, Quaternion.identity); }
      	}
	}
}

			
						
									
function SelectRoomOrHall() {
        hallDirection = Random.Range(1, 3);
        roomHeight = 1;
        roomWidth = 1;
        if (hallDirection == 1)
            roomWidth = Random.Range(minRoomWidth, maxRoomWidth); //pick random room width
        else if (hallDirection == 2)
            roomHeight = Random.Range(minRoomHeight, maxRoomHeight); //pick random room height
        else if (hallDirection > 2) {
			roomWidth = Random.Range(minRoomWidth, maxRoomWidth); //pick random room width
			roomHeight = Random.Range(minRoomHeight, maxRoomHeight); } //pick random room height
		else
        	roomDraw = false;
}




function FindWallTile() {
	while (gameDungeon[roomX, roomY] < northWall || gameDungeon[roomX, roomY] > westWall) { // loop until a wall tile has been found
    	roomX = Random.Range(roomWidth + 3, dungeonWidth - (roomWidth + 3)); //pick random x,y co-ordinates for dungeon tile
		roomY = Random.Range(roomHeight + 3, dungeonHeight - (roomHeight + 3)); //make sure co-ordinates will be within the bounds of array when room drawn
		doorX = roomX; //set room start co-ordinates as door tile to be used later
		doorY = roomY;
		if (gameDungeon[roomX, roomY] == northWall) {//mark which direction the wall faces
			wallDirection = "n";
			roomY = roomY - roomHeight;
			roomStartTile = Random.Range(0, roomWidth); //randomly select how far to one side or the other the door is for the new room
			roomX = roomX - roomStartTile; } //reset the starting draw point for the room based on the door location
		else if (gameDungeon[roomX, roomY] == southWall) {
			wallDirection = "s";
			roomY = roomY + 1;
			roomStartTile = Random.Range(0, roomWidth);
			roomX = roomX - roomStartTile; }
		else if (gameDungeon[roomX, roomY] == eastWall) {
			wallDirection = "e";
			roomX = roomX + 1;
			roomStartTile = Random.Range(0, roomHeight);
			roomY = roomY - roomStartTile; }
		else if (gameDungeon[roomX, roomY] == westWall) {
			wallDirection = "w";
			roomX = roomX - roomWidth;
    		roomStartTile = Random.Range(0, roomHeight);
  			roomY = roomY - roomStartTile; }
  	}
}

		
				
						
function CheckRoomLimits() {
    for (var tileCount = 0; tileCount < (roomWidth * roomHeight); tileCount++) {
    	for (var y = 0; (y < roomHeight); y++ ) {
        	for (var x = 0; (x < roomWidth); x++ ) {
                if (gameDungeon[(roomX + x), (roomY + y)] > roomCorner) //check if floor tiles inside room will fit new location
                    roomDraw = false; //if they don't, signal the loop to break and restart
                if (gameDungeon[(roomX + x), (roomY - 1)] > horizontalDoor) //check if north wall tiles will fit
                    roomDraw = false;
                if (gameDungeon[(roomX + x), (roomY + roomHeight)] > horizontalDoor) //check if south wall tiles will fit
                    roomDraw = false;
                if (gameDungeon[(roomX + roomWidth), (roomY + y)] > horizontalDoor) //check if east wall tiles will fit
                    roomDraw = false;
                if (gameDungeon[(roomX - 1), (roomY + y)] > horizontalDoor) //check if west wall tiles will fit
                    roomDraw = false;
            }
        }
    }
    
    if (gameDungeon[roomX - 1, roomY - 1] > horizontalDoor) //check if northwest corner tile will fit
        roomDraw = false;
    else if (gameDungeon[roomX + roomWidth, roomY - 1] > horizontalDoor) //check if northeast corner tile will fit
        roomDraw = false;
    else if (gameDungeon[roomX - 1, roomY + roomHeight] > horizontalDoor) //check if southwest corner tile will fit
        roomDraw = false;
    else if (gameDungeon[roomX + roomWidth, roomY + roomHeight] > horizontalDoor) //check if southeast corner tile will fit
        roomDraw = false;
}		




function AddDoorToRoom() {
	if (wallDirection == "n" || wallDirection == "s") //draw vertical door based on wall tile
		gameDungeon[doorX, doorY] = verticalDoor;
	else if (wallDirection == "e" || wallDirection == "w") //draw horizontal door based on wall tile
		gameDungeon[doorX, doorY] = horizontalDoor;
}
								


																								
function GenerateRooms() {
	//START_ROOM_GENERATION:
	while (roomCount < (maxRooms + maxHalls)) { //keep making rooms until maxmium rooms created that were specified
    	roomDraw = true; //reset variables
       	roomX = 1;
       	roomY = 1;
		SelectRoomOrHall();
		FindWallTile();
		CheckRoomLimits();
		if (roomDraw == true) {
   			//draw the room, and count up the room counter, and add the door
   			DrawRoomTilesToArray();
   			CountUpRooms();
   			AddDoorToRoom(); }
	}
}

I have a feeling it’s something to do with marking the roomDraw variable as false/true but I can’t seem to track it down. Either that or the room counter is off…

In Pseudo, it draws the first room with the default variables, but then checks to see if it can attach another room or hall depending on the boundaries, and keeps looping until it finds a solution, then counts the room and starts again until it reaches the max rooms/halls. If I cut out the generate room function, it will output the first room to the screen perfectly, so i’m almost positive it’s something I’ve messed up in the generate room function. I’m also not sure if random.range, is the right way to select random numbers. I’m really new to unity as you can probably tell. :S

Random.Range with integers is exclusive and won’t work the way you have it (e.g. Random.Range(1, 3) will only ever generate 1 or 2); see the docs for the integer overload. I haven’t looked at the script in much detail, but I see 128 width * 128 height, which if you’re generating a GameObject for each cell, would be 16384 separate objects, which is far too many and could be the cause of locking up Unity. Typically you’d use the Mesh class to generate combined chunks so you don’t have so many objects. This does increase code complexity quite a bit, but is vastly more efficient.

–Eric

Thanks for your help! that makes sense. I was going by this:

And saw that they were both inclusive, but i guess that’s a float so that means there’s only a .01 chance (out of 1 integer) of getting the max number? Or does it round down all the time? Either way, I made the changes and it’s not locking up Unity anymore. I also reduced the array to 64 x 64, but now i’m running in to out of range errors, so i’m trying to track that down too. In C# i had it working perfectly (although the code was really ugly), but I could output that to the console so it was really easy to debug.

EDIT: Oops nevermind, it’s still doing the same thing. I don’t think it’s a performance issue. I had it running on a C# script with 256 x 256 grid and it ran super quick. I have it running at 64 x 32 now.

Aha! Amazing what a little bracket will do. I found the issue.

This:

function FindWallTile() {

    while (gameDungeon[roomX, roomY] < northWall || gameDungeon[roomX, roomY] > westWall) { // loop until a wall tile has been found

        roomX = Random.Range(roomWidth + 3, dungeonWidth - (roomWidth + 3)); //pick random x,y co-ordinates for dungeon tile

        roomY = Random.Range(roomHeight + 3, dungeonHeight - (roomHeight + 3)); //make sure co-ordinates will be within the bounds of array when room drawn

This should have been the only part of the function looping, and not the whole function.