Level generator freezing on creating bigger level?
Hey All!
I'm trying to write a level generator that builds a maze with pre made room prefabs. The generator checks the room prefab for possible doors (North, East, South, West) and picks one randomly. Then it checks if the place for the next room is still empty on the grid. As long as I keep the amount of steps (so how many rooms are going to spawn) to 10, it works. The moment I try more, Unity freezes. I'm a beginning coder, so there must be some bad coding in here :P still, I hope someone can check my scripts and help me with this, cuz I don't know why this is happening! Any help/ tip is appreciated!
first the grid:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LevelGrid : MonoBehaviour {
public int gridSizeX = 10;
public int gridSizeZ = 10;
[SerializeField] private int cellSizeX = 10;
[SerializeField] private int cellSizeZ = 10;
public GameObject floorTile;
public int[,] grid;
List<Vector2> gridPos = new List<Vector2>();
public Vector2 coord;
public List<Vector2> usedCoordinates = new List<Vector2>();
void Start () {
grid = new int[gridSizeX, gridSizeZ];
for (int z = 0; z < gridSizeZ; z++)
{
for (int x = 0; x < gridSizeX; x++)
{
Vector3 pos = new Vector3(x * cellSizeX, 0, z * cellSizeZ);
//Instantiate(floorTile, pos, Quaternion.Euler(-90, 0, 180));
gridPos.Add(VecToCo(pos));
}
}
}
//vector to Coordinates
public Vector2 VecToCo (Vector3 position)
{
int x = (int)position.x / cellSizeX;
int z = (int)position.z / cellSizeZ;
coord = new Vector2(x, z);
return coord;
}
//Coordinates to Vec3
public Vector3 CoToVec (Vector2 coord)
{
int x = (int)coord.x;
int z = (int)coord.y;
Vector3 vecPos = new Vector3(x * cellSizeX, 0, z*cellSizeZ);
return vecPos;
}
//check for empty
public bool IsEmpty(Vector2 coordinates)
{
if (usedCoordinates.Contains(coordinates))
{
return false;
}
else return true;
}
//look North
public Vector2 LookNorth(Vector2 coordinates)
{
Vector3 temp = CoToVec(coordinates);
Vector3 temp2 = temp += new Vector3(0, 0, 1 * cellSizeZ);
return VecToCo(temp2);
}
//look East
public Vector2 LookEast(Vector2 coordinates)
{
Vector3 temp = CoToVec(coordinates);
Vector3 temp2 = temp += new Vector3(1 * cellSizeX, 0, 0);
return VecToCo(temp2);
}
//look South
public Vector2 LookSouth(Vector2 coordinates)
{
Vector3 temp = CoToVec(coordinates);
Vector3 temp2 = temp += new Vector3(0, 0, -1 * cellSizeZ);
return VecToCo(temp2);
}
//look West
public Vector2 LookWest(Vector2 coordinates)
{
Vector3 temp = CoToVec(coordinates);
Vector3 temp2 = temp += new Vector3(-1 * cellSizeX, 0, 0);
return VecToCo(temp2);
}
}
Then the spawner:
using System.Collections; using System.Collections.Generic; using System.Linq; using UnityEngine;
public class MazeSpawner : MonoBehaviour
{
public GameObject[] roomN;
public GameObject[] roomE;
public GameObject[] roomS;
public GameObject[] roomW;
public GameObject fourDoors;
public int steps;
private GameObject choosenDoor;
List<Vector3> doorTransforms = new List<Vector3>();
public LevelGrid levelGrid;
public List<GameObject> roomList = new List<GameObject>();
void Start()
{
//clear list
doorTransforms.Clear();
//first room
Vector3 pos = levelGrid.CoToVec(new Vector2(levelGrid.gridSizeX / 2, levelGrid.gridSizeZ / 2));
if (levelGrid.IsEmpty(levelGrid.VecToCo(pos)))
{
GameObject lastRoom = Instantiate(fourDoors, pos, Quaternion.Euler(-90, 0, 180));
roomList.Add(lastRoom);
levelGrid.usedCoordinates.Add(levelGrid.VecToCo(pos));
FindDoors(lastRoom);
}
//spawn rooms
for (int i = 0; i < steps;)
{
switch (choosenDoor.name)
{
case "DoorN":
if (levelGrid.IsEmpty(levelGrid.LookNorth(levelGrid.VecToCo(roomList.Last().transform.position))))
{
SpawnRoom("North");
doorTransforms.Add(choosenDoor.transform.position);
i++;
}
else
{
doorTransforms.Add(choosenDoor.transform.position);
FindDoors(choosenDoor.transform.parent.gameObject);
Debug.Log("door N found in switch but no free space!");
}
break;
case "DoorO":
if (levelGrid.IsEmpty(levelGrid.LookEast(levelGrid.VecToCo(roomList.Last().transform.position))))
{
SpawnRoom("East");
doorTransforms.Add(choosenDoor.transform.position);
i++;
}
else
{
doorTransforms.Add(choosenDoor.transform.position);
FindDoors(choosenDoor.transform.parent.gameObject);
Debug.Log("door O found in switch but no free space!");
}
break;
case "DoorZ":
if (levelGrid.IsEmpty(levelGrid.LookSouth(levelGrid.VecToCo(roomList.Last().transform.position))))
{
SpawnRoom("South");
doorTransforms.Add(choosenDoor.transform.position);
i++;
}
else
{
doorTransforms.Add(choosenDoor.transform.position);
Debug.Log("door Z found in switch but no free space!");
FindDoors(choosenDoor.transform.parent.gameObject);
}
break;
case "DoorW":
if (levelGrid.IsEmpty(levelGrid.LookWest(levelGrid.VecToCo(roomList.Last().transform.position))))
{
SpawnRoom("West");
doorTransforms.Add(choosenDoor.transform.position);
i++;
}
else
{
doorTransforms.Add(choosenDoor.transform.position);
FindDoors(choosenDoor.transform.parent.gameObject);
Debug.Log("door W found in switch but no free space!");
}
break;
default:
Debug.Log("no door found in switch");
break;
}
}
}
void SpawnRoom(string direction)
{
Vector2 dir;
GameObject chooseRoom;
GameObject newRoom;
switch (direction)
{
case "North":
dir = (levelGrid.LookNorth(levelGrid.VecToCo(roomList.Last().transform.position)));
chooseRoom = roomS[Random.Range(1, roomS.Length)];
newRoom = Instantiate(chooseRoom, levelGrid.CoToVec(dir), Quaternion.Euler(-90, 0, 180));
roomList.Add(newRoom);
levelGrid.usedCoordinates.Add(dir);
FindDoors(newRoom);
break;
case "East":
dir = (levelGrid.LookEast(levelGrid.VecToCo(roomList.Last().transform.position)));
chooseRoom = roomW[Random.Range(1, roomS.Length)];
newRoom = Instantiate(chooseRoom, levelGrid.CoToVec(dir), Quaternion.Euler(-90, 0, 180));
roomList.Add(newRoom);
levelGrid.usedCoordinates.Add(dir);
FindDoors(newRoom);
break;
case "South":
dir = (levelGrid.LookSouth(levelGrid.VecToCo(roomList.Last().transform.position)));
chooseRoom = roomN[Random.Range(1, roomS.Length)];
newRoom = Instantiate(chooseRoom, levelGrid.CoToVec(dir), Quaternion.Euler(-90, 0, 180));
roomList.Add(newRoom);
levelGrid.usedCoordinates.Add(dir);
FindDoors(newRoom);
break;
case "West":
dir = (levelGrid.LookWest(levelGrid.VecToCo(roomList.Last().transform.position)));
chooseRoom = roomE[Random.Range(1, roomS.Length)];
newRoom = Instantiate(chooseRoom, levelGrid.CoToVec(dir), Quaternion.Euler(-90, 0, 180));
roomList.Add(newRoom);
levelGrid.usedCoordinates.Add(dir);
FindDoors(newRoom);
break;
default:
Debug.LogError("Not a valid direction in void SpawnRoom");
break;
}
}
GameObject FindDoors(GameObject lastRoom)
{
Transform[] child2arr = lastRoom.transform.Cast<Transform>().ToArray();
choosenDoor = child2arr[Random.Range(0, child2arr.Length)].gameObject;
if (doorTransforms.Contains(choosenDoor.transform.position))
{
for (int i = 0; i < child2arr.Length; i++)
{
choosenDoor = child2arr[i].gameObject;
if (!doorTransforms.Contains(choosenDoor.transform.position))
{
return choosenDoor;
}
}
return choosenDoor;
//while (doorTransforms.Contains(choosenDoor.transform.position))
//{
// choosenDoor = child2arr[Random.Range(0, child2arr.Length)].gameObject;
//}
//return choosenDoor;
}
else
{
return choosenDoor;
}
}
}
Answer by elmidiachi · May 14, 2018 at 11:08 AM
Alright! Turns out, the 'while' loop or the for loop at the FindDoors() screwed things up and makes an infinite loop once the steps get higher. Changed it, now it works like a charm!
Your answer
Follow this Question
Related Questions
How to automatically generate a new int with a specific name? 1 Answer
How to generate the Top and Right border for my game's arena? 0 Answers
Any good procedural generated maze for 2d out there? 0 Answers
Unity Crashes When Clicking Play: Script Error? 1 Answer
Unity 2D: Game freezes after the first frame of a particular animation 1 Answer