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
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:
Or this:
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:
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
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:
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)
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.
Scripting hints
- 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
. 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.)