Dungeon Generator not generating the set amount of rooms

I’ve spent the past couple of days toying with a dungeon generator. I made lots of progress (with some help of course :wink: ). However, I’ve run into a new problem.

After implementing a system that continues spawning rooms in a set direction for k amount of times, the number of rooms generated became substantially lower than the set amount should be.

For example, I want to spawn 150 rooms-- 107 spawn.

I feel like this has something to do with the for loop that deals with these “direction repeats” (lines 55-70), but maybe not?

Any suggestions on how I could begin to fix this would be extremely appreciated!

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 numberOfRooms;
    public int maxDirectionRepeat = 1;
    #endregion

    public int roomNumber;

    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();
    }

    void InitialIteration() //Create rooms
    {
        List<Vector3Int> occupiedCoordinates = new List<Vector3Int>();
        Vector3Int currentPosition = Vector3Int.zero;

        for(int i = 0;  i < numberOfRooms; i++)
        {
            List<Vector3Int> possibleSpawnDirections = new List<Vector3Int>();

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

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

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

                    if (!occupiedCoordinates.Contains(possiblePosition))
                    {
                        currentPosition = currentPosition + (chosenDirection * roomSize);
            
                        occupiedCoordinates.Add(currentPosition);
                        GameObject instantiatedRoom = Instantiate(room_prefab, currentPosition, Quaternion.identity);

                        roomNumber++;
                        instantiatedRoom.name = "Room_" + roomNumber;

                        i++; //make sure to increase i, becuase if you don't, these "repeated rooms" wont count towards the total room count
                    }
                    else
                    {
                        print("no more available spots!");
                        currentPosition = occupiedCoordinates[Random.Range(0, occupiedCoordinates.Count)];
                    }                    
                }
            }
            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)];
            }
        
        }
        
    
    
    }
}

That’s an excellent hypothesis. Now test it with debugging!

If your hypothesis is correct, fix it. If not, test another hypothesis.

In any case, staring at code is rarely a way to fix it.

By debugging you can find out exactly what your program is doing so you can fix it.

Use the above techniques to get the information you need in order to reason about what the problem is.

You can also use Debug.Log(...); statements to find out if any of your code is even running. Don’t assume it is.

Once you understand what the problem is, you may begin to reason about a solution to the problem.

Okay, I found and fixed the issue.

I realized that the for-loop (lines 59-84) has to finish running even if the while-loop conditions are met. So even if roomNumber is greater than maxRooms, if the for-loop isn’t finished, it doesn’t matter, and more rooms will be spawned until it finishes.

I simply added an if statement inside the for-loop to only alow code to be run if roomNumber is less than maxRooms.

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;

    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();
    }

    void InitialIteration() //Create rooms
    {
        List<Vector3Int> occupiedCoordinates = new List<Vector3Int>();
        Vector3Int currentPosition = Vector3Int.zero;

        //for(int i = 0;  roomNumber < numberOfRooms; i++)
        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;

                        }
                        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)];
            }
        
        }
        
    
    
    }
}