List

Content creation is one the most time-consuming aspects of game development. One way you can design levels quicker and easier is by creating a tile-based game. A tile-based game has a playfield that consists of small rectangular, square, or hexagonal pieces, referred to as tiles.

This playfield, or tilemap could imagined as a grid of blocks where every block is given a number or ID. Based on the ID, the game will determine how that position on the grid is drawn and how it should behaves when a player interacts with it.

This tutorial will show you how to add tilemaps to create levels within a simple platformer title by using the newly added Tilemaps feature in the Unity Editor and explore how you can create custom behaviors for your tiles through writing script so if you are looking to create levels quickly using minimal art assets, this tutorial is a great place to start!

This is a beginner level tutorial, but you should be familiar with Unity’s interface. If you are new to Unity or need a refresher on the basic concepts, check out Unity’s built in documentation on the subject.

Getting Started

First, download the starter project and open the project in Unity. You will need at least version 2017.2 of Unity.

The art assets used for this tutorial were created by the incredibly talented Kenney. You can find more information about him as well as his art assets at: http://kenney.nl/

Once the project is loaded, hit the play button to verify the project is running correctly.

At this point you should be able to see the player character fall off the screen since there’s nowhere for him to land on. Thankfully, this is something that is very easy for us to fix.

Unit Size

If you select the Scene tab, you may notice that there are gray lines crisscrossing the screen creating a grid within our game environment. Each of these squares has a width and height of 1 Unity unit which is how all objects in the world are positioned.

Unity’s physics engine also considers one Unity unit to be equal to 1 meter by default.

You can see this relationship between position and Unity units yourself if you select the Player object in our scene:

From the Inspector tab you can see that the Transform component on the Player object has the Position property set to (0, 2.5, 0). This means that the player is positioned 2.5 units above the center of the world.

Pixels Per Unit

For 2D games, each sprite is scaled based on the number of pixels in the image. By default, Unity considers 100 pixels to be 1 Unity unit in size. With that in mind, if you create sprites that are 100px x 100px in size they will fit within the grid. However, this is not something that is guaranteed. To see the size of our image, you will need to go to the Project taband then open up the Sprites\Tiles folder. Upon selecting one of the images you should notice the Inspector tab will display the sprite’s properties:

From the picture above you can see:

At the bottom of the tab you will see information on the actual size of the image that Unity is using. In this case the tile is 128 ×128 pixels in size.

Also notice the Pixels Per Unit property. As mentioned above, this is what tells Unity how large you want this image to be scaled when brought into the game.

Try creating an object for this sprite now by dragging it from the Project tab and dropping it in the Scene tab. You should notice that it looks something like this:

Notice that the size of the tile is larger than 1 unit. In fact, since you now know that the image is 128 x 128 pixels in size and that the Pixels Per Unit property on this object is 100, it can be inferred that the tile is exactly 1.28 Unity units wide and long.

This can easily change this scale by modifying the Pixels Per Unit property. To do that:

  • Select the tile again in the Project tab.
  • In the Inspector window change the Pixels Per Unit to 128
  • then select the Apply button.

You will now notice that the size of the tile in the Scene view has scaled down and is now matching the size of the grid perfectly.

  • The example tile is no longer needed, so delete the example tile object from the Scene that you made (select it and then press the Delete key) and then select all of the other tile objects from the Project tab in the Sprites\Tiles folder
  • Once they are all selected, change the Pixels Per Unit property to 128 and hit the Apply button.

Intro to the Tile Palette

Much like a traditional palette allows painters to arrange and mix paints, Unity’s Tile Palette window allows you to place tiles there to hold before using them on the tilemap itself.

To open up the Tile Palette window in your project, go into the top menu bar and select Window | Tile Pallete. This will open the Tile Palette as a floating window that you can move anywhere you want by clicking and dragging the tab with its name. I will drag and drop it on top of the Inspector tab  so it will replace that space as you can see below:

Before you can start drawing tiles you first have to create a palette to hold the tiles. To do this select the Create New Palette option underneath the Tile Palette tools. This will display the Create New Palette pop-up for you to select the type of palette you want:

  1. Under Name enter Platformer Palette
  2. Then select the Create button.
  3. You’ll be asked what folder you’d like to save the palette in. Go ahead and create a new folder in the Assets folder
    called Palettes and save it there.

Creating Tiles

Now that you have a palette to put tiles on, you now need to add a tile to the palette to draw. Thankfully, it’s very easy to create basic tiles:

From the Project tab go into the Assets/Sprites/Tiles folder and drag and drop a sprite into the space on the Tile Palette. Once you let go it will ask you to select where you want the tile to be saved. Create a new folder in the Assets folder called Tiles and save it there.

After this you should see the new tile inside of the Tile Palette!

Right now, the displayed palette seems quite large. This can be adjusted moving the mouse over the Palette and then using the mouse wheel to zoom in and out. The middle mouse button will allow you to pan the camera, and you can select whatever tile you’d like to use via left clicking.

Once you have a tile on the Tile Palette, you can select them to draw on any tilemap in the project…. but there aren’t any yet. That sounds like a good thing to do next.

Building a Tilemap

To build a tilemap you will go to the top menu bar and select GameObject | 2D Object | Tilemap.

This will create two new game objects, one parented to the other, in the Hierarchy tab:

  • Grid – Contains the Grid component which contains information about the size of each cell, the gap (if any) between tiles, and the Cell Swizzle which dictates how the cells will be drawn.
  • Tilemap – Contains two new components: the Tilemap and the Tilemap Renderer which allow users to customize how the tilemap will be drawn and how it is oriented.

These two objects allow you to draw tiles onto the screen using the palette that was created previously.

Drawing tiles onto the Tilemap

The tile palette has a number of ways that one can draw tiles to the screen:

  1. Select Tool – Selects an area of the grid
  2. Move Tool – Move selection to another place
  3. Paint Tool – Paints with the active brush
  4. Rectangle Tool – Paint a rectangle with the active brush
  5. Picket Tool – Pick tiles from the tilemap to paint with
  6. Erase Tool – Will remove tiles from the tilemap
  7. Fill Tool – Will paint the entire area

 

Using the Paint Tool

To get started, go ahead and click on the tile you placed on the Tile Palette earlier. You should see that the Paint Tool with automatically get turned on by default (the button with the paintbrush on it). Once selected, move the mouse over to the Scene tab and draw a platform underneath of the player by left-clicking to place tiles.

After all that setup, we finally have tiles on the screen!

If your tiles are not matching the size of the grid, you may either modify the Grid component’s Tile Size property or you may modify the Pixels Per Unit property mentioned earlier in the Unit Size section above.

Erasing Tiles

There’s always the possibility of making mistakes. To remove those you can make use of the Tile Palette’s Erase Tool. To use the Erase Tool you can either select the eraser icon from the top of the Tile Palette or you can hold down the Shift button and then click where ever you’d like to remove a tile.

Using the Rectangle Tool

As great as drawing everything by hand is, it would be a lot quicker to draw boxes instead of placing each tile individually.

For this example, add the other dirt tile to the Tile Palette for placement by dragging and dropping the grassCenter sprite from the Project tab in the Assets\Sprites\Tiles folder into the Tile Palette beside the original tile. Just like the first tile, Unity will ask you where to save the new tile, again place it in the Assets\Tiles folder.

Afterwards, click on your new tile in the palette and then select the rectangle tool. Once selected, then start dragging and dropping below your platforms to fill in the spots below your platforms.

As you can see, it’s a lot quicker to create boxes using this tool than clicking and dragging each tile by hand! Placing boxes like this is really useful for blocking out an area quickly for testing (sometimes referred to as greyboxing). Once you’ve playtested the level you can go in later and then add additional details and polish the level up.

Duplicating platforms using the Picker Tool

Often, you will want to replicate content you’ve made previously so you can reuse and tweak it later. The picker tool allows you to do that.

From the Tile Palette select the Picker Tool and click and drag from the top left to a lower section of one of the platforms created. When you release the mouse button you should notice a duplicate of your selection following your mouse. If you click on the mouse you should see the duplicate placed there. Use this to create another platform.

Tweaking items using Select and Move

Platformer games often require a lot of tweaking to create levels that feel and play well, such as making a platform 1 unit lower than before or to add or remove spaces between jumps. The Select and Move Tools allow you to do this easily.

Select the Select Tool (mouse button icon)  and drag and drop a set of tiles. After selected click on the Move Tool  (arrow icon) and then click and drag to shift the tiles around.

Making Tilemaps Interactable

As great as your map currently looks, when you play the game the player will still fall through the level. To make the tilemaps interact with the player we can make use of a special collider created for tilemaps, the Tilemap Collider 2D component.

From the Hierarchy window select the Tilemap GameObject. With it selected add a Tilemap Collider 2D component to the object by going to the top toolbar and selecting Component | Tilemap | Tilemap Collider 2D.

After that you should notice green boxes on all of the tiles of our tilemap:

Just like when we add colliders on traditional Game Objects, these boxes represent the collision data that the physics engine uses to determine if two objects are colliding. If you select the Player you can notice that it already has a Box Collider 2D component attached which also shows a green box when selected in the Scene tab. When two objects with 2D colliders hit each other and at least one of them has a Rigidbody 2D component attached with a Body Type set to Dynamic (which the Player does) the object with the Rigidbody will react to collision events.

If all goes well, at this point if you play the game you should notice your player will now be able to land and walk on the tiles correctly!

If you are interested in learning more about how Physics works in 2D and 3D games in Unity, I suggest you check my previous book Unity 5.x Game Development Blueprints.

 

Working with Layers

Once we have a Tilemap Collider 2D component attached to a tilemap, all of the tiles will cause the player to collide with it. Having collision is great, but what if you wanted to have tiles that did not have collisions, such as some props? The simplest solution would be to create a second tilemap to put all of the things we do not want to collide with. This can work well, but if we put tiles at the same position on both tilemaps, by default we will not know which one will be drawn on top of the other one. To solve this, we can use the properties of the Tilemap Renderer component to customize how things will be drawn.

Create a new tilemap by selecting the Grid object in the Hierarchy window and then selecting GameObject | 2D Object |Tilemap from the top menu.
Select the new tilemap that was just created and give it a new name of Upper Layer by going to the top of the Inspector tab, selecting the name and modifying it. Once you finish naming the object press the Enter key to confirm the change.

Scroll down to the Tilemap Renderer component and set the Order in Layer property to 1.

By default the property is set to 0 so by putting a 1 here we are saying that this tilemap should be drawn on top of the previous one. In the starter project you may notice that the Background objects already have an Order in Layer of -1 in the Sprite Renderer component to ensure that the other objects will be drawn on top.

For those of you already familiar with working in 2D, Sorting Layers work just like they do normally as well.

Adding Props

Now that you have a new layer, it is time to add some visual flair to the level.

Open the Tile Palette tab and note the Active Tilemap property. This will show what the current tilemap you are going to be drawing on is. We want to draw on the new tilemap so under the Active Tilemap dropdown select Upper Layer.

Next, go to the Project tab and open the Assets\Sprites\Props folder. As you can see, we have a number of new sprites that can be used as tiles in order to add more visual variation in the level to make things less boring and improve the look of your level.

Select all of the files in the folder at once by first clicking on the spring sprite. Afterwards, hold down the Shift key and then select the bridgeA sprite. From there drag and drop all of the sprites onto the Tile Palette. While doing this, make sure that you do not drop your  tiles on top of the tiles that are already there.  Once you release the mouse you’ll be asked to select a folder to place all the tiles. Select the Assets\Tiles folder and select the Select Folder option.

If all went well, you should see the Tile Palette fill up with all of the new tiles in one quick step!

Be sure to save your project after modifying the Tile Palette or you might lose any changes made.

Once you have all of the props in, add a few of them over your level:

After this, not only does the level look much better, but if you play the game now you will see that your player can walk through the prop tiles in the Upper Layer while still colliding with the previously created tilemap!

Custom Tiles with Code

Everything that has been done so far has given a good foundation to the tile map system in general, but there are other benefits that you can get by adding on to what is already created. Currently, we have to place all of the tiles we want to have in our level by hand. Sometimes this leads to tedious things that need to be done, such as making sure that the grass tile is always placed on the top part of all of the platforms we wish to have in the game.

One way that you can make your life easier is to write some code to have this done choice made automatically. Thankfully, Unity has made it possible for us to create our very own custom tiles with unique behavior associated with it. s

Go to the Project window and open up the Assets/Scripts folder. From there, right click in the window and select Create | C# Script. Once the file has been created, give it a name of PlatformTile and then double click on it to open the script up for you to edit in your IDE of choice.

The first thing to do in the file is to add a new using statement at the top of the file:

using UnityEngine.Tilemaps; // Tile

As the comment above indicates, this line allows you to access the Tile  class. The reason why we want to have access to the Tile class is the fact that PlatformTile will actually inherit from Tile instead of the normal MonoBehaviour that you may be used to using.

Speaking of which, you will want to replace the class definition with the following lines:

// Makes it so we can create one of these inside of the Unity Editor
[CreateAssetMenu(fileName = "PlatformTile", menuName = "Platform Tile")]
public class PlatformTile : Tile {

Having PlatformTile inherit from Tile  means that the PlatformTile class has the functionality of the Tile  class but we can replace or add new functionality and variables to make the class do whatever it is you want.

You may also notice the CreateAssetMenu attribute. This allows you to create a file of this type through the Create menu in the Project tab which will be used when we want to create the actual tile for us to place.

For more information on the CreateAssetMenu attribute, check out: https://docs.unity3d.com/ScriptReference/CreateAssetMenuAttribute.html

For the PlatformTile class, the goal is for the sprite for the tile to change based on the other objects that are placed near it. If there is a tile above the once that was placed, a body tile should be placed. However if there’s nothing above, then the grass tile should be placed. Since there are two possible sprites to be drawn, there will be two variables to hold which ones to draw.  To do so, we can add two new properties to the PlatformTile class:

public Sprite topTile;
public Sprite bodyTile;

To see the code in action, save the script and then return to the Unity Editor. From the Project tab, go to the Assets\Tiles folder. From there, right click within the tiles and then select Create | Platform Tile.

If you select the newly created object, you should notice in the Inspector tab that in addition to the default Tile  class properties, there also is the Top Tile and the Body Tile variables that were defined in the script that was written previously. This is because the variables were marked as public in the script.

Assign the dirtMid sprite from the Sprites\Tiles folder to Top Tile and dirtCenter to the Body Tile property.

In order to be able to see a representation of this tile in the Tile Palette, drag the dirtMid sprite into the Sprite property at the top of the component as well.

At this point, you can go to the Tile Palette tab and drag and drop the PlatformTile object onto the palette and you’ll see it appear just like a normal sprite, and it can be drawn on like a normal sprite. But now you will customize its behavior to draw different sprites via conditions.

Open up the PlatformTileclass once again and first remove the Start and Update functions as they don’t do anything as they do not exist in the Tile class.

The first function to implement is a helper-function that will be called in the other functions that you will write:

// Will return if the tile given at position is the same type as ours or not
public bool IsSameTile(ITilemap tilemap, Vector3Int position)
{
    // Will retrieve the tile at the given position of the map if it exists
    var tile = tilemap.GetTile(position);

    // Need to check if there is a tile
    if (tile != null)
    {
        // Attempt to turn the tile into a PlatformTile
        var platformTile = tile as PlatformTile;

        // If the conversion is successful, that means the tile is 
        // the same class, but could have different sprites used
        if (platformTile != null)
        {
            // If the tile sprites are the same then this is the same tile
            if (platformTile.bodyTile == this.bodyTile)
            {
                return true;
            }
        }
    }

    // If any point fails then the answer is false
    return false;
}

This function will return if a tile at a certain position is the same type as this class’. This information will be used to determine if the tile should draw the grass or the normal sprite.

Updating Tiles

There are two main functions that are used to update tiles in the Tile class: GetTileData which determines what tile to draw and RefreshTile which will be called anytime a tile is placed.

To start off with, add the following function to the script:

// Is in charge of the rendering data of the tile
public override void GetTileData(Vector3Int position, ITilemap tilemap, ref TileData tileData)
{
    // Sets up original sprite to display using the tile given under Sprite
    base.GetTileData(position, tilemap, ref tileData);

    // When then will replace with the top tile
    tileData.sprite = topTile;

    // If there is something above us, use the body tile instead
    if (IsSameTile(tilemap, position + Vector3Int.up))
    {
        tileData.sprite = bodyTile;
    }
}

The GetTileData function is called each time whenever a tile needs to be drawn. Note the override keyword which is stating that we are going to be replacing the default behavior given by the Tile class. We do want to use the original version  of the function so the first thing I do is call the parent’s version of GetTileData through the base keyword. Afterwards you check if there is a tile above you of the same type. If it is, the tile above the current one should have the grass, so this will will use the ground sprite instead (bodyTile). Otherwise, if there is nothing above this tile, then the grass (topTile) will be used.

For more information on the override keyword check out: https://docs.microsoft.com/en- us/dotnet/csharp/language-reference/keywords/override

Next, add the following function to the script:

public override void RefreshTile(Vector3Int position, ITilemap tilemap)
{
    // Call the parent class' version of this file
    base.RefreshTile(position, tilemap);

    // Check if there is a tile below us or not
    Vector3Int abovePosition = position + Vector3Int.up;

    // Will return if the tile above ours is the same as this one
    if (IsSameTile(tilemap, abovePosition))
    {
        tilemap.RefreshTile(abovePosition);
    }

    Vector3Int belowPosition = position + Vector3Int.down;
    // Will return if the tile above ours is the same as this one
    if (IsSameTile(tilemap, belowPosition))
    {
        tilemap.RefreshTile(belowPosition);
    }

}

The RefreshTile function is called whenever a tile is placed on the tilemap. In this case, aside from the default behavior the script will check if there is a tile above or below this current tile that is the same type. If there is, those tiles should be refreshed to ensure that the each of the tiles will draw the correct information as the map has been updated. The parent class’ version of RefreshTile calls the GetTileData function that was written so the sprite of the tile should be updated correctly.

Save your script and head back into the Unity Editor. Go to the Tile Palette and change the Active Tilemap to Tilemap. From there select your Platform Tile and start placing tiles.

And with that, you can see that your tile reacts appropriately, automatically putting the top tile when needed and the body otherwise!

Where To Go From Here?

At this point, you should have a good handle on Unity’s new Tilemap tools. You have saw how to create a Grid, Tile Palette, and Tilemap. You’ve placed numerous tiles into the Palette and saw how to bring them into your scenes in an effective manner. You also learned how to create a custom tile of your own which will work differently depending on the conditions of how it is placed.

You’ve gone through a lot, but you have only scratched the surface when it comes to building custom tiles of your own. If you’re interested in diving into Scriptable Tiles, I highly suggest checking out Unity’s Manual documentation as well as their 2D-Extras repository on github. The repository includes a number of other common example tiles that many would like to have.

If you ran into any issues, download the completed project here.

  Posts

1 2 3 5
December 7th, 2017

Unity 2017 Tilemap Tutorial

Content creation is one the most time-consuming aspects of game development. One way you can design levels quicker and easier […]

January 7th, 2017

Visual;Conference 2017

As a part of Visual;Conference 2017, I was invited to give a talk on Game Engines for the development of […]

November 11th, 2014

Unity Game Development Blueprints Released!

My fifth title, and first Unity title, is now out! In this book I took feedback from my previous books […]

May 6th, 2014

Video Series UDK Game Development Released!

My fourth title published by Packt is now out! Unlike previous entries this is a video series and delves into […]

December 17th, 2013

Benefits and drawbacks of using Kismet

As with any job it is important to use the tool that is appropriate for it. UDK provides three ways […]

November 20th, 2013

Types of Collision in UDK

As you may know, a lot of the interactivity from games comes from the ability to have objects interact with […]

August 19th, 2013

Guest appearance on CrunchCast

Recently I had the privilege to talk to Chris Holden on CrunchCast about myself, my books, and Unreal in general. […]

August 18th, 2013

Getting Started with UDK – UnrealScript

This post will be the most useful for those who have already read or are currently reading my latest book, […]

June 8th, 2013

Flash 101: An Introduction

As you begin your project, there may be many new panels and areas that are yours to use.   Stage […]

June 8th, 2013

Setting up Flash CS6 to use Scaleform with UDK

Currently, I am in the middle of writing my third book with Packt Publishing, this book on creating a single project over […]