Search Unity

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

Discussion in 'In-Editor Tutorials Packages' started by DrJkJones, Aug 21, 2022.

?

Did this help you?

  1. Yes :)

    66.7%
  2. No :(

    16.7%
  3. I was just curious about this post :)

    16.7%
  1. DrJkJones

    DrJkJones

    Joined:
    Jan 9, 2022
    Posts:
    21
    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 :D

    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:
    Screen Shot 2022-08-21 at 12.43.36 PM.png
    Or this:
    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: 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".
    Code (CSharp):
    1. using UnityEngine;
    2. public class LevelGenerator : MonoBehaviour {
    3.     public GameObject[] rooms;
    4.     public GameObject[] corridors;
    5.     [SerializeField] int numberOfLevels;
    6.     [SerializeField] Transform roomHolder;
    7.     int levels;
    8.     int lastDirection;
    9.     int randomDirection;
    10.     void Start() {
    11.         numberOfLevels = Random.Range(25, 50);
    12.         GameObject newRoom = Instantiate(rooms[4], transform.position, Quaternion.identity);
    13.         newRoom.transform.parent = roomHolder.transform;
    14.         Instantiate(corridors[0], new Vector2(transform.position.x + 9, transform.position.y - 2), Quaternion.identity);
    15.         transform.position = new Vector2(transform.position.x + 18f, transform.position.y);
    16.         randomDirection = 1;
    17.         levels++;
    18.     }
    19.     void Update() {
    20.         if (levels < numberOfLevels - 1) {
    21.             MakeNextRoom();
    22.             levels++;
    23.         } else if (levels == numberOfLevels - 1) {
    24.             if (randomDirection == 1) {
    25.                 GameObject newRoom = Instantiate(rooms[1], transform.position, Quaternion.identity);
    26.                 newRoom.transform.parent = roomHolder.transform;
    27.             } else if (randomDirection == 2) {
    28.                 GameObject newRoom = Instantiate(rooms[4], transform.position, Quaternion.identity);
    29.                 newRoom.transform.parent = roomHolder.transform;
    30.             } else {
    31.                 GameObject newRoom = Instantiate(rooms[8], transform.position, Quaternion.identity);
    32.                 newRoom.transform.parent = roomHolder.transform;
    33.             }
    34.             levels++;
    35.         }
    36.     }
    37.     void MakeNextRoom() {
    38.         if (!(levels == numberOfLevels)) {
    39.             GameObject newRoom = Instantiate(rooms[0], transform.position, Quaternion.identity);
    40.             newRoom.transform.parent = roomHolder.transform;
    41.             lastDirection = randomDirection;
    42.             randomDirection = Random.Range(1, 4);
    43.             // Right = 1, Left = 2, Up = 3!
    44.             if (randomDirection == 1 && lastDirection == 2) { randomDirection = 2; } else if (randomDirection == 2 && lastDirection == 1) { randomDirection = 1; }
    45.             if (randomDirection == 3) {
    46.                 Destroy(newRoom);
    47.                 if (lastDirection == 1) {
    48.                     GameObject newNewRoom = Instantiate(rooms[3], transform.position, Quaternion.identity);
    49.                     newNewRoom.transform.parent = roomHolder.transform;
    50.                 } else if (lastDirection == 2) {
    51.                     GameObject newNewRoom = Instantiate(rooms[6], transform.position, Quaternion.identity);
    52.                     newNewRoom.transform.parent = roomHolder.transform;
    53.                 } else if (lastDirection == 3) {
    54.                     GameObject newNewRoom = Instantiate(rooms[7], transform.position, Quaternion.identity);
    55.                     newNewRoom.transform.parent = roomHolder.transform;
    56.                 }
    57.             } else if (lastDirection == 3) {
    58.                 Destroy(newRoom);
    59.                 // Need a way to know what the next direction will be (to determine 2 or 5)!
    60.                 if (randomDirection == 1) {
    61.                     GameObject newNewRoom = Instantiate(rooms[5], transform.position, Quaternion.identity);
    62.                     newNewRoom.transform.parent = roomHolder.transform;
    63.                 } else {
    64.                     GameObject newNewRoom = Instantiate(rooms[2], transform.position, Quaternion.identity);
    65.                     newNewRoom.transform.parent = roomHolder.transform;
    66.                 }
    67.             }
    68.             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); }
    69.             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); }
    70.         }
    71.     }
    72. }
    (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: 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) 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.

    - 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 :confused:. Feel free to check and/or copy the code above.

    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.)
     
  2. RikuTheFuffs-U

    RikuTheFuffs-U

    Unity Technologies

    Joined:
    Feb 20, 2020
    Posts:
    440
    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!
     
    vamosfa and DrJkJones like this.
  3. DrJkJones

    DrJkJones

    Joined:
    Jan 9, 2022
    Posts:
    21
    That sounds awesome, I'll check it out! Thank you!
     
  4. XDylie

    XDylie

    Joined:
    Apr 18, 2021
    Posts:
    1
    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!