Procedural Generation in Unity (Tutorial)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] hi I'm well and this video is about procedural generation in unity I'm going to walk you through how to randomly generate a dungeon map and it's going to be based on the dungeons from games like The Legend of Zelda and The Binding of Isaac to get started we want to think about how this is actually going to work our dungeon map is going to be made out of different rooms these rooms can be imagined as fitting on a grid even though not every space will be used we're going to want to make a two-dimensional array they can hold data about these rooms but what kind of array we use for this you may have made a race for things like vector twos or intz but in this case we'll actually want to make our own room class this can hold all the data we might need we can hold references to multiple data types and it can be added to in the future now it's time to get into unity go into the project panel and create a new C sharp script mine is going to be called room note that this script does not inherit from mana behavior think of this class more like a container for data this section is called a constructor which is used to pass information into an instance once created which will be convenient restoring a vector to fourth position and in to describe the type of room and pools to say whether or not doors are in certain positions note that if you have many room types you might want to use a character or string to store that data but an INT will do fine for the two room types we'll use in this tutorial it's time to start our level generation script create a empty game object and put a script on it mine is going to be called level generation we can start by defining how big the level is in room lengths my script upstream visas half extents so the actual size is double this we'll also need to make a 2d array of rooms don't forget that comma in the brackets it might seem a little odd to keep a vector - list of taking positions since that information is technically in the room array but it'll be much easier to search if a position is taken using the contains method from a list in the start function I do a little math to make sure that there aren't more rooms and fit in the grid that it cost separate functions one of which is the one we're about to create called create rooms let's break down this create rooms method first we'll set the room array to be the proper size remember that I'm using half extents here it's time to make our first room it seems best to put the starting point of the room at the center of the grid so that we'll have plenty of room to sprout in any direction the center of the grid is just at grid size x and y we have two values to fill in for that constructor we made earlier we'll want the position at 0 0 to make it the center of the scene when we eventually draw the map note that this is an offset from the array values if we have the starting room at 0 0 in the array we would only be able to make rooms to the right and bottom of the beginning room for our example the room type will be 1 2 references this is the starting room you can have room types for all kinds of things but in this tutorial it will only be normal rooms and 1 starting room let's go over the main loop of this algorithm I'm going to go through the logic of this loop before breaking down the separate methods it's referencing first we're setting up a loop that will run once for each room we want make after that we're doing a bit of math which will determine some odds in a couple of lines then we're grabbing any valid position to spawn a run this next part is designed to make the map more interestingly shapes so it's up to your own interpretation of how it should be done I noticed when first making this script that the rooms were very clumped together this part will make it so that some rooms will clump but others will branch out the amount that does this is determined by the magic numbers above the lip and how many rooms are left to create they're listed as magic numbers but in reality it's just a bit of math it's set up so that the farther we are into the loop there's less of a chance that we will attempt to branch out for the times that we want to branch out we just keep trying to find a new position that has only one neighbor that connects it now that we have our positions it's time to add it to the array and take a position list we just make sure to calculate the offset for the array while we create the room we construct the room with our new position and a type of zero which represents a normal room if you're doing something more complicated with room types I suggest you do that in a separate method once the layout of the map is complete that doesn't fit the scope of this tutorial though let's go over how we're grabbing new positions we need to grab a valid position for this algorithm a valid position will be any one that is adjacent to a room that already exists since they all need to be connected we're going to grab a random taken position from our list then randomly select whether we're going up down left or right we will keep going through the loop until the position has not already taken and make sure it's within our rooms boundaries the selective position method is just a slight modification of the previous one here when we grab the starting position we make sure we're grabbing one that only has one neighbor this separate method is just meant to add to the branching effect when we want it finding the number of neighbors a given room has is actually fairly straightforward but it is vital to the several parts of the script we just start with an int at zero and increment it for each side this contained within taking positions we're almost ready to draw the map we need to know how these rooms connect to each other now that we have our full map we can just go through each room and check where the rooms around it are located this for loop messes in a for loop structure will allow us to check every position in the 2d array if there's no room there we'll continue to the next check in the loop otherwise we'll check each of the cardinal directions to see if there's a room while being careful to avoid numbers that don't fit in the array with that done it's time to draw our map but first we'll even make game objects that will make up the map for my map I'm using 15 basic sprites and arranging them to fit the layout each sprite is 16 by 8 with a 1 pixel gutter then I can fill with the doors for that image this way I have an image for every possible combination of the cardinal directions mine is white so it can be easily colored however I want I made a game object with a sprite renderer component and made a script on it called map sprite assignor here we will need references to sprites so that we can assign them in the inspector you can use an array for this if you want it would be cleaner code but also a little more confusing later which is why I did this way we'll also need to have some variables that will be set from the room data and a couple colors for different room types in start we just set up a couple things then call other methods to keep things clean in pic sprite we have to do a really ugly if statement tree it's more tedious than anything if there are more options I suggest generating an image at runtime but this is probably the best way to do it there's only 50 options the pic color method is a bit of a relief after that last one it just assigns the color of the sprite based on the type of erm it is there are other ways to do this if you want to have a lot more room types for this fits our needs the last thing to note about the script is that when you are assigning the color in the inspector make sure you change the Alpha value to make it opaque for some reason you know you default custom colors to transparent if you miss this you might have a totally working system that doesn't show anything because all the rooms are drawn transparent now we can finally draw our map this is the final stretch and this part is pretty painless we make a method in the level generation script and just loop through every point in our Marea we grab the position of that room and multiply that by the size of our map sprite then we instantiate it and sets variables according to the room it represents so now we can see that every time we start the level you get a new randomly generated map you can mess around with these variables to see what kind of different maps you'll get or even set them to public and change them in the inspector don't forget the same data we're using to generate this map to be turned into a fully functional level if you want me to go over how to do that in a future video or you want any more information on how this works let me know down in the comments and be sure to subscribe so you don't miss any tutorials thanks for following along I'm trying out a new format for this tutorial so let me know what you think see you in the next video
Info
Channel: Six Dot
Views: 58,278
Rating: undefined out of 5
Keywords: procedural generation, unity, dungeon map, binding of isaac, legend of zelda, tutorial, procedural, generation
Id: nADIYwgKHv4
Channel Id: undefined
Length: 10min 29sec (629 seconds)
Published: Fri Oct 06 2017
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.