Been working on a dungeon generator...+

As a quick little project, I created a little dungeon generator! It works like a charm, and I’ll probably use it in future projects.

Here’s the code-- feel free to use it or give any feedback :slight_smile:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class DungeonGenerationManager : MonoBehaviour
{
    public GameObject room_prefab;
    public int roomSize;

    #region GENERATION SETTINGS
    public int maxRooms;
    public int maxDirectionRepeat = 1;
    #endregion

    public int roomNumber;
    bool deadEnd = false;

    List<Vector3Int> occupiedCoordinates;
    List<GameObject> spawnedRooms;

    private static readonly List<Vector3Int> roomDirections = new List<Vector3Int>()
    {
        Vector3Int.forward,
        Vector3Int.back,
        Vector3Int.right,
        Vector3Int.left,
        //Vector3Int.up,
        // Vector3Int.down

    };
    private void Start()
    {
        InitialIteration();
        SecondIteration();
    }

    void InitialIteration() //Create rooms
    {
        occupiedCoordinates = new List<Vector3Int>();
        spawnedRooms = new List<GameObject>();

        Vector3Int currentPosition = Vector3Int.zero;

        while(roomNumber < maxRooms)
        {
            deadEnd = false;

            List<Vector3Int> possibleSpawnDirections = new List<Vector3Int>();

            for(int i = 0; i < roomDirections.Count; i++)
            {
                Vector3Int possibleDirection = roomDirections[i];
                if(!occupiedCoordinates.Contains(currentPosition + possibleDirection * roomSize))
                {
                    possibleSpawnDirections.Add(possibleDirection);
                }
            }

            if(possibleSpawnDirections.Count > 0 && !deadEnd)
            {
                Vector3Int chosenDirection = possibleSpawnDirections[Random.Range(0, possibleSpawnDirections.Count)];

                int repeatTime = Random.Range(1, maxDirectionRepeat);
                for(int j = 0; j < repeatTime; j++) //keep generating in this direction k times
                {
                    Vector3Int possiblePosition = currentPosition + (chosenDirection * roomSize);

                    if(roomNumber < maxRooms) //the for-loop has to finish even if the conditions of the while-loop are met. If roomNumber is greater than maxRooms, but the for-loop isn't done,
                                              //then more rooms will be spanwed regardless that we are above are room limit. This is why this if statement is here. Everything in the for-loop will only be run if the conditions are met. 
                    {
                        if (!occupiedCoordinates.Contains(possiblePosition))
                        {
                            currentPosition = currentPosition + (chosenDirection * roomSize);
            
                            occupiedCoordinates.Add(currentPosition);

                            roomNumber++;

                            GameObject instantiatedRoom = Instantiate(room_prefab, currentPosition, Quaternion.identity);
                            instantiatedRoom.name = "Room_" + roomNumber;

                            spawnedRooms.Add(instantiatedRoom);

                        }
                        else
                        {
                            print("no more available spots!");
                            currentPosition = occupiedCoordinates[Random.Range(0, occupiedCoordinates.Count)];
                            deadEnd = true;
                        } 
                    }                   
                }
            }
            else //if there are no more available positions left, choose a random occupied position and branch from there!
            {
                print("no more available spots!");
                currentPosition = occupiedCoordinates[Random.Range(0, occupiedCoordinates.Count)];
            }
        
        }

    }

    //make the room object have child 0 be the north wall, child 1 be the south wall, child 2 be the east wall, and child 3 be the west wall, to match the indices of the room directions list (i.e Vector3Int.forward is list item 0, and the north wall is child 0)

    void SecondIteration()
    {
        foreach(GameObject room in spawnedRooms)
        {
            Vector3Int roomPos = new Vector3Int((int)room.transform.position.x, (int)room.transform.position.y, (int)room.transform.position.z);

            for (int i = 0; i < roomDirections.Count; i++)
            {
                Vector3Int possibleDirection = roomDirections[i];
                if (occupiedCoordinates.Contains(roomPos + possibleDirection * roomSize))
                {
                    room.transform.GetChild(i).gameObject.SetActive(false); //remember the floor is the first child
                }
            }
        }
    }
}