[Tutorial] How to make random level generation in unity 2D!

Hey all! I have been working really hard on creating randomly generated levels in the past few days, and I finally succeeded. Hopefully I'll be able to save you some time :smile:

First off, this generator is designed for platformers, not top down games, so I'm sorry if this doesn't help you.
Anyway, here's what the end result will look like:
8379279--1104813--Screen Shot 2022-08-21 at 12.43.36 PM.png
Or this:
8379279--1104816--Screen Shot 2022-08-21 at 12.43.16 PM.png
Or it could look completely different, since that's the beauty of random level generation.

Anyway, the first thing to do is create prefabs of each room, you'll need rooms with exits that match the ones I made:8379279--1104819--Screen Shot 2022-08-21 at 12.46.56 PM.png

Afterwards, we'll write our script, if you want to try and work it out on your own, don't show the spoiler and skip to the spoiler titled "Scripting hints".
My Script

[spoiler]

using UnityEngine;
public class LevelGenerator : MonoBehaviour {
    public GameObject[] rooms;
    public GameObject[] corridors;
    [SerializeField] int numberOfLevels;
    [SerializeField] Transform roomHolder;
    int levels;
    int lastDirection;
    int randomDirection;
    void Start() {
        numberOfLevels = Random.Range(25, 50);
        GameObject newRoom = Instantiate(rooms[4], transform.position, Quaternion.identity);
        newRoom.transform.parent = roomHolder.transform;
        Instantiate(corridors[0], new Vector2(transform.position.x + 9, transform.position.y - 2), Quaternion.identity);
        transform.position = new Vector2(transform.position.x + 18f, transform.position.y);
        randomDirection = 1;
        levels++;
    }
    void Update() {
        if (levels < numberOfLevels - 1) {
            MakeNextRoom();
            levels++;
        } else if (levels == numberOfLevels - 1) {
            if (randomDirection == 1) {
                GameObject newRoom = Instantiate(rooms[1], transform.position, Quaternion.identity);
                newRoom.transform.parent = roomHolder.transform;
            } else if (randomDirection == 2) {
                GameObject newRoom = Instantiate(rooms[4], transform.position, Quaternion.identity);
                newRoom.transform.parent = roomHolder.transform;
            } else {
                GameObject newRoom = Instantiate(rooms[8], transform.position, Quaternion.identity);
                newRoom.transform.parent = roomHolder.transform;
            }
            levels++;
        }
    }
    void MakeNextRoom() {
        if (!(levels == numberOfLevels)) {
            GameObject newRoom = Instantiate(rooms[0], transform.position, Quaternion.identity);
            newRoom.transform.parent = roomHolder.transform;
            lastDirection = randomDirection;
            randomDirection = Random.Range(1, 4);
            // Right = 1, Left = 2, Up = 3!
            if (randomDirection == 1 && lastDirection == 2) { randomDirection = 2; } else if (randomDirection == 2 && lastDirection == 1) { randomDirection = 1; }
            if (randomDirection == 3) {
                Destroy(newRoom);
                if (lastDirection == 1) {
                    GameObject newNewRoom = Instantiate(rooms[3], transform.position, Quaternion.identity);
                    newNewRoom.transform.parent = roomHolder.transform;
                } else if (lastDirection == 2) {
                    GameObject newNewRoom = Instantiate(rooms[6], transform.position, Quaternion.identity);
                    newNewRoom.transform.parent = roomHolder.transform;
                } else if (lastDirection == 3) {
                    GameObject newNewRoom = Instantiate(rooms[7], transform.position, Quaternion.identity);
                    newNewRoom.transform.parent = roomHolder.transform;
                }
            } else if (lastDirection == 3) {
                Destroy(newRoom);
                // Need a way to know what the next direction will be (to determine 2 or 5)!
                if (randomDirection == 1) {
                    GameObject newNewRoom = Instantiate(rooms[5], transform.position, Quaternion.identity);
                    newNewRoom.transform.parent = roomHolder.transform;
                } else {
                    GameObject newNewRoom = Instantiate(rooms[2], transform.position, Quaternion.identity);
                    newNewRoom.transform.parent = roomHolder.transform;
                }
            }
            if (randomDirection == 1) { Instantiate(corridors[0], new Vector2(transform.position.x + 9, transform.position.y - 2), Quaternion.identity); } else if (randomDirection == 2) { Instantiate(corridors[0], new Vector2(transform.position.x - 9, transform.position.y - 2), Quaternion.identity); } else { Instantiate(corridors[1], new Vector2(transform.position.x, transform.position.y + 5), Quaternion.identity); }
            if (randomDirection == 1) { transform.position = new Vector2(transform.position.x + 18f, transform.position.y); } else if (randomDirection == 2) { transform.position = new Vector2(transform.position.x - 18f, transform.position.y); } else if (randomDirection == 3) { transform.position = new Vector2(transform.position.x, transform.position.y + 10f); }
        }
    }
}

(Disregard the comments, I forgot to clean them up once I finished)
Anyway, a few things will need to be tailored to your prefabs, for instance the movement after making each room (be sure to leave space for the corridors if you are adding them too), and the specific array values. I set up my array like so:8379279--1104822--Screen Shot 2022-08-21 at 12.51.29 PM.png
One important note as well, the room holder is for organization, I structured my hierarchy like so (in case you're wondering what in the world is going on)8379279--1104825--Screen Shot 2022-08-21 at 12.54.50 PM.png
The "Level Generation Setup" GameObject is just for organization, the "Levels" one is just for storing all the instantiations of rooms (I forgot to move corridors there too and I'm too tired to do that now). The "Level Generator" GameObject is the important one, it holds the "Level Generator" script.

[/spoiler]

Scripting hints

[spoiler]

  • I used arrays to hold the prefabs
  • I would store which room I made last in a variable as well as the one that is currently being made
  • The order of storing the data and instantiation matters a lot
  • I had to destroy quite a few rooms after creation to form corner rooms
  • Still stuck? I don't blame you, it took me forever. It doesn't help either that I'm not good at teaching :face_with_spiral_eyes:. Feel free to check and/or copy the code above.

[/spoiler]

Anyway, that's how I did it. I hope this helps you! Btw, it's my first forum post, so if it's confusing feel free to send a response and I'll try to clarify. If you have a question about the purpose of pieces (or all) of the code, feel free to ask me (didn't want to explain the whole thing at the time of writing this). Regardless, I hope you have a great day and stay creative! (If the images don't show, let me know, I was having some issues with them.)

Hi @DrJkJones !
First of all, thanks for the tutorial: It's great to see that you're trying to help other people achieving their goals to make the ultimate Platformer game.

However, this particular forum is dedicated to the In-Editor Tutorial Packages (Tutorial Framework and Authoring tools) and tutorials made with them!

Did you know about those Editor packages? They could really help you make some awesome tutorials that you can run directly in the editor, so you can save a lot of time by not having to make screenshots and go back and forth between the forum and the editor to help other people.

We just released a new version of them: here 's the announcement. Why don't you try them out? I'd be really curious to see what kind of amazing tutorials you could do with tools like that!

2 Likes

That sounds awesome, I'll check it out! Thank you!

Thank you Very much for this information! I have looked on youtube all day for any tutorials relating to Platform Generation and yours is the first one I have come across! I love the idea and wasnt sure if this was the right method THANK YOU!