---
title: "Level Generation"
content_type: tutorial
url: "https://learn.unity.com/course/intermediate-3d-game-development/unit/2d-roguelike-tutorial-legacy/tutorial/level-generation?language=en"
language: en
container_type: course
container_title: "Intermediate 3D Game Development"
container_url: "https://learn.unity.com/course/intermediate-3d-game-development.md?language=en"
unit_title: "2D Roguelike"
unit_url: "https://learn.unity.com/course/intermediate-3d-game-development/unit/2d-roguelike-tutorial-legacy?language=en"
standalone_markdown_url: "https://learn.unity.com/tutorial/level-generation.md?language=en"
previous_title: "2D Roguelike Setup and Assets"
previous_url: "https://learn.unity.com/course/intermediate-3d-game-development/unit/2d-roguelike-tutorial-legacy/tutorial/2d-roguelike-setup-and-assets?language=en"
previous_markdown_url: "https://learn.unity.com/course/intermediate-3d-game-development/unit/2d-roguelike-tutorial-legacy/tutorial/2d-roguelike-setup-and-assets.md?language=en"
next_title: "Unit Mechanics"
next_url: "https://learn.unity.com/course/intermediate-3d-game-development/unit/2d-roguelike-tutorial-legacy/tutorial/unit-mechanics?language=en"
next_markdown_url: "https://learn.unity.com/course/intermediate-3d-game-development/unit/2d-roguelike-tutorial-legacy/tutorial/unit-mechanics.md?language=en"
difficulty: intermediate
duration_minutes: 25
unity_version:
  - "5.x"
supported_unity_versions:
  - name: "5.x"
    url: "https://learn.unity.com/tutorial/level-generation.md?language=en&version=5.x"
last_updated: "2026-08-04T14:23:03.000Z"
---

# Level Generation

Implement BoardManager and GameManager scripts to generate 2D roguelike levels and manage game states.

This next part of the [2D Roguelike project](https://learn.unity.com/project/2d-roguelike-tutorial) addresses writing the BoardManager script that will procedurally generate levels and the GameManager script for managing game states.

## Materials

- [2D Roguelike Project Assets](https://www.assetstore.unity3d.com/en/#!/content/29825)

## 1. Writing the Board Manager

This is part 4 of 14 of the 2D Roguelike tutorial in which we write the BoardManager script which will procedurally or semi-randomly generate our levels.

[Video](http://www.youtube.com/watch?v=bvvaqAbpPjc)

## BoardManager

```csharp
using UnityEngine;
using System;
//Allows us to use Lists.
using System.Collections.Generic;
//Tells Random to use the Unity Engine random number generator.
using Random = UnityEngine.Random;

namespace Completed

{

    public class BoardManager : MonoBehaviour
    {
        // Using Serializable allows us to embed a class with sub properties in the inspector.
        [Serializable]
        public class Count
        {
            public int minimum;             //Minimum value for our Count class.
            public int maximum;             //Maximum value for our Count class.


            //Assignment constructor.
            public Count (int min, int max)
            {
                minimum = min;
                maximum = max;
            }
        }


        public int columns = 8;             //Number of columns in our game board.
        public int rows = 8;                //Number of rows in our game board.
        //Lower and upper limit for our random number of walls per level.
        public Count wallCount = new Count (5, 9);
        //Lower and upper limit for our random number of food items per level.
        public Count foodCount = new Count (1, 5);
        public GameObject exit;             //Prefab to spawn for exit.
        public GameObject[] floorTiles;     //Array of floor prefabs.
        public GameObject[] wallTiles;      //Array of wall prefabs.
        public GameObject[] foodTiles;      //Array of food prefabs.
        public GameObject[] enemyTiles;     //Array of enemy prefabs.
        public GameObject[] outerWallTiles; //Array of outer tile prefabs.

        //A variable to store a reference to the transform of our Board object.
        private Transform boardHolder;
        //A list of possible locations to place tiles.
        private List <Vector3> gridPositions = new List <Vector3> ();


        //Clears our list gridPositions and prepares it to generate a new board.
        void InitialiseList ()
        {
            //Clear our list gridPositions.
            gridPositions.Clear ();

            //Loop through x axis (columns).
            for(int x = 1; x < columns-1; x++)
            {
                //Within each column, loop through y axis (rows).
                for(int y = 1; y < rows-1; y++)
                {
                    //At each index add a new Vector3 to our list with the x and y coordinates of that position.
                    gridPositions.Add (new Vector3(x, y, 0f));
                }
            }
        }


        //Sets up the outer walls and floor (background) of the game board.
        void BoardSetup ()
        {
            //Instantiate Board and set boardHolder to its transform.
            boardHolder = new GameObject ("Board").transform;

            //Loop along x axis, starting from -1 (to fill corner) with floor or outerwall edge tiles.
            for(int x = -1; x < columns + 1; x++)
            {
                //Loop along y axis, starting from -1 to place floor or outerwall tiles.
                for(int y = -1; y < rows + 1; y++)
                {
                    //Choose a random tile from our array of floor tile prefabs and prepare to instantiate it.
                    GameObject toInstantiate = floorTiles[Random.Range (0,floorTiles.Length)];

                    //Check if we current position is at board edge, if so choose a random outer wall prefab from our array of outer wall tiles.
                    if(x == -1 || x == columns || y == -1 || y == rows)
                        toInstantiate = outerWallTiles [Random.Range (0, outerWallTiles.Length)];

                    //Instantiate the GameObject instance using the prefab chosen for toInstantiate at the Vector3 corresponding to current grid position in loop, cast it to GameObject.
                    GameObject instance = Instantiate (toInstantiate, new Vector3 (x, y, 0f), Quaternion.identity) as GameObject;

                    //Set the parent of our newly instantiated object instance to boardHolder, this is just organizational to avoid cluttering hierarchy.
                    instance.transform.SetParent (boardHolder);
                }
            }
        }


        //RandomPosition returns a random position from our list gridPositions.
        Vector3 RandomPosition ()
        {
            //Declare an integer randomIndex, set it's value to a random number between 0 and the count of items in our List gridPositions.
            int randomIndex = Random.Range (0, gridPositions.Count);

            //Declare a variable of type Vector3 called randomPosition, set it's value to the entry at randomIndex from our List gridPositions.
            Vector3 randomPosition = gridPositions[randomIndex];

            //Remove the entry at randomIndex from the list so that it can't be re-used.
            gridPositions.RemoveAt (randomIndex);

            //Return the randomly selected Vector3 position.
            return randomPosition;
        }


        //LayoutObjectAtRandom accepts an array of game objects to choose from along with a minimum and maximum range for the number of objects to create.
        void LayoutObjectAtRandom (GameObject[] tileArray, int minimum, int maximum)
        {
            //Choose a random number of objects to instantiate within the minimum and maximum limits
            int objectCount = Random.Range (minimum, maximum+1);

            //Instantiate objects until the randomly chosen limit objectCount is reached
            for(int i = 0; i < objectCount; i++)
            {
                //Choose a position for randomPosition by getting a random position from our list of available Vector3s stored in gridPosition
                Vector3 randomPosition = RandomPosition();

                //Choose a random tile from tileArray and assign it to tileChoice
                GameObject tileChoice = tileArray[Random.Range (0, tileArray.Length)];

                //Instantiate tileChoice at the position returned by RandomPosition with no change in rotation
                Instantiate(tileChoice, randomPosition, Quaternion.identity);
            }
        }


        //SetupScene initializes our level and calls the previous functions to lay out the game board
        public void SetupScene (int level)
        {
            //Creates the outer walls and floor.
            BoardSetup ();

            //Reset our list of gridpositions.
            InitialiseList ();

            //Instantiate a random number of wall tiles based on minimum and maximum, at randomized positions.
            LayoutObjectAtRandom (wallTiles, wallCount.minimum, wallCount.maximum);

            //Instantiate a random number of food tiles based on minimum and maximum, at randomized positions.
            LayoutObjectAtRandom (foodTiles, foodCount.minimum, foodCount.maximum);

            //Determine number of enemies based on current level number, based on a logarithmic progression
            int enemyCount = (int)Mathf.Log(level, 2f);

            //Instantiate a random number of enemies based on minimum and maximum, at randomized positions.
            LayoutObjectAtRandom (enemyTiles, enemyCount, enemyCount);

            //Instantiate the exit tile in the upper right hand corner of our game board
            Instantiate (exit, new Vector3 (columns - 1, rows - 1, 0f), Quaternion.identity);
        }
    }
}
```

## 2. Writing the Game Manager

This is part 5 of 14 of the 2D Roguelike tutorial in which we write the GameManager script which will manage the state of our game.

[Video](http://www.youtube.com/watch?v=7NYXBUWmFvU)

## GameManager

```csharp
using UnityEngine;
using System.Collections;
using System.Collections.Generic;        //Allows us to use Lists. 

    public class GameManager : MonoBehaviour
    {
        //Static instance of GameManager which allows it to be accessed by any other script.
        public static GameManager instance = null;
        //Store a reference to our BoardManager which will set up the level.
        private BoardManager boardScript;
        //Current level number, expressed in game as "Day  1".
        private int level = 3;

        //Awake is always called before any Start functions
        void Awake()
        {
            //Check if instance already exists
            if (instance == null)

                //if not, set instance to this
                instance = this;

            //If instance already exists and it's not this:
            else if (instance != this)

                //Then destroy this. This enforces our singleton pattern, meaning there can only ever be one instance of a GameManager.
                Destroy(gameObject);    

            //Sets this to not be destroyed when reloading scene
            DontDestroyOnLoad(gameObject);

            //Get a component reference to the attached BoardManager script
            boardScript = GetComponent<BoardManager>();

            //Call the InitGame function to initialize the first level 
            InitGame();
        }

        //Initializes the game for each level.
        void InitGame()
        {
            //Call the SetupScene function of the BoardManager script, pass it current level number.
            boardScript.SetupScene(level);

        }



        //Update is called every frame.
        void Update()
        {

        }
    }
```

## Loader

```csharp
using UnityEngine;
using System.Collections;


    public class Loader : MonoBehaviour 
    {
        public GameObject gameManager;            //GameManager prefab to instantiate.
        public GameObject soundManager;            //SoundManager prefab to instantiate.


        void Awake ()
        {
            //Check if a GameManager has already been assigned to static variable GameManager.instance or if it's still null
            if (GameManager.instance == null)

                //Instantiate gameManager prefab
                Instantiate(gameManager);

            //Check if a SoundManager has already been assigned to static variable SoundManager.instance or if it's still null
            if (SoundManager.instance == null)

                //Instantiate SoundManager prefab
                Instantiate(soundManager);
        }
    }
```

Are you stuck? [Let a qualified expert get you across the finish line.](https://livehelp.unity.com/client/question/?utm_campaign=connect_americas_acquisition_2019-LiveHelp-Launch&utm_content=LIVEHELP_LEARN-01-all&utm_medium=link&utm_source=learn)
