Friday, July 3, 2015

The Power of Perlin. Civilization style Maps Part 1.



Perlin Noise, Unity, and Civilization Style Maps.


Welcome to the start of this blog where I explore various topics aimed at first time solo developers starting with Unity. To begin with I am going to do a series where I explore Perlin noise and the many ways it can be used to procedurally generate content for your games. So with that lets begin!

What is Perlin Noise?


The first thing I recommend is that you read the Unity library entry for Perlin noise located here. That grey scale map isn't very useful for much though so lets explore what is going on so we can make use of it. In the example the Perlin noise call takes two inputs, in this case the x coordinate and the y coordinate modified by some math and returns a value at that point. This value is then passed to the image generator which changes the grey scale value at that point. Whats important to realize at this point is that you don't have to pass that value to a grey scale generator, you can pass it to whatever you want!

In this first part we are going to pass the Perlin noise to a very basic generator that creates land and water based on the input. In later entries we will also so add other terrain features such as mountains and forests but for now lets create out basic map.

Setting Up The Scene.


Asset Download.

Before we begin writing our code lets take a few minutes to set up our scene. First open unity and create a new project, or open the project you would like to use this in. Then go to the link above and download the assets we will use in this tutorial. With both these things done lets start creating.


Start by creating three folders under assets. The names should be Models, Scripts, and Prefabs. Next take the assets and import them into models. You should now have the left image. You will also notice that when we imported the models unity created default materials for them and put them in a materials folder. Open that folder and delete the two materials found in there. With both of those deleted go ahead and import the material assets into this folder.



 The final step before we begin coding our map is to create prefabs from these models. In order to do this make a empty object in the scene. Rename the empty object and drag the dirt model underneath it in the hierarchy. Finally drag the material onto the model. Now drag the object from the scene into the Prefab folder and you have created a prefab. Repeat it for the water.



 

Delete the objects from the scene and we are done with the setup.

Lets Code.


Highlight the scrips folder, right click and create a new C# script. We will call it tileGenerator. Lets start by deleting the void update function. In a later entry we will look at infinite terrain but for now we want the map to create once as the player enters the game.


To begin with we are going to create some variables. All of these will be placed before the start function. First of these are two arrays of GameObjects that will hold our prefab models. The reason we are making them arrays is at a later date we may want to add multiple water models and this will allow us to do that. Add a comment above that is meaningful, and then build. We will be hitting build often as it helps us know where bugs in the code have appeared.










We are going to building our map  on the X and Z plane. In Unity the default physics settings treat Y as up down, and later if we want to make use of those, building the ground plane on the X and Z plane will be important. These next two variables then are the X and Z dimensions of the map we wish to make. We make them public so we can change there values from within the editor or from another script.



We now need a way to manipulate the ratio of land to water. To do this we will create a float and call it water level. It will be looking for a value ideally between 1 and 0. This is because our Perlin noise function will return a value between 1 and 0 as explained in our dictionary entry.

 

 The final public variable we are going to make is the resolution variable. This variable is how we manipulate the output of our Perlin noise.





With all those variables lets get to work using them. We are going to place all the code into its own function, and then call that function from start so lets do that.



Now everything from here will be placed inside the function. The way we are creating the map is for each grid in our range, we will take the Perlin noise and determine if it should be water or ground. So to begin with we will need to cycle through all our square and the way we will do that is with two for loops. If you are unsure of loops and how they work, check the unity tutorials located here.



Have you been remembering to build as you go?

Next up we create the inputs for the Perlin noise and the Perlin noise itself. by using x and z in the inputs we make the Perlin noise specific to that grid coordinate.



At this point if we wanted to we could create a grey scale map just like the example, instead lets use it to make a real map for a game. The way we will do this is dividing the output of the Perlin noise into two groups. If the Perlin noise if greater than the water level value, we want ground to spawn. If it is lower then the water level we want water to spawn. Now write these two if statements.






Lets start with the water. We want to take our game object from the array and instantiate it to the x and z coordinates. To do that we use the unity Instantiate command, which will take our GameObject and create a copy at the location we specify. To allow us to easily add models once we have them ready lets write the code as if there is more than one, and we want it to randomly call one of those models.




 Now copy and paste our water code into the ground if statement replacing all the water references with ground.

 


 The last code we need to write is the call during start to our function so go ahead and do that.



Now build it one last time and lets return to the editor. Create an empty game object, call it Map, and then assign the script to it by dragging it onto the object. Now when we click on map we should see a panel on the right where we can put in all our public variables and assign our arrays.


All that's left to do is to assign the prefabs to the arrays by dragging them over and entering values for all our variables. Try the following.



Now when you click play some land and water should appear.



There you have it, the start of our map. Its pretty basic at the moment and there is lots of things we can do but that's it for this part. As this is my first tutorial and my first real crack at any sort of professional coding I would love to hear from you. Send me an email or leave a comment below and now that your in wilderness with me, survive and thrive.