Unity 2017.2 adds a new feature I’m very excited about, and have wished existed for a very long while: 2D Tilemaps. I like using Tilemaps in my games, I’m no artist and I find the barrier a lot lower to entry with using 2D art. And there are a large number of existing tilesets available for free online that finding simple placeholder tiles is very easy.
I’ve experimented with several 3rd party extensions in the past, and when I couldn’t find one that did everything I wanted it to, I even wrote my own. However I found all of these to be either buggy, slow, or difficult to use (including mine!) I recently downloaded Unity 2017.2 to give the new Tilemap features a spin. I’ve spent the last couple days doing just that, and I’ve got to say, I’m pretty excited. Everything I’ve seen to indicates to me that the Tilemap will be a very welcome addition to Unity. That said, at first I had trouble wrapping my head around the way Tilemaps in Unity work. It’s a bit of a break from the existing way Unity does a lot of things. Once I spent enough time with it though, in though things started making sense. This article is a short walk-through of what I’ve learned about the last couple days. It will mostly cover the basics, it won’t be going into too much depth, but will hopefully make understanding the 2D tilemaps a bit easier.
So without further ado, lets dive right in. We’ll first look at the UI Unity exposes in the editor for working with Tiles, then we’ll deeper to look at the underlying Tilemap system.
Once we’ve fired up Unity 2017.2 or later and create a sample project, we don’t have to poke around long to see the new ‘Tilemap’ options in the Create GameObject menu
Clicking that will create 2 objects in our scene
- A Grid
- A Tilemap
The grid defines the size and layout of the tilemap. The Tilemap itself defines what tiles are where. The tilemap can be layered by adding additional Tilemaps under the same grid.
Currently the grid only supports Rectangular tiles, but the experimental preview had support for hexagonal grids at some point, so hopefully that will make a return in a later update. The other properties the grid has control the size of the tiles and the gap between the tiles. There is also a property called swizzle allows you to rearrange the axis the tilemap uses. We don’t need to change anything here right now.
The Timemap object contains a couple components, a Tilemap and a Tilemap renderer. There’s not too much interesting here either, and the properties they contain are pretty straightforward so I won’t spend time going over them.
So now that we have a Tilemap, we’ll probably want to be adding some tiles. To add tiles from the Editor we will need a Tile Palette. This is an Asset type, but not one we can create from the project window. Instead we’ll need to open the ‘Tile Palette’ window from Windows -> Tile Palette
On the Palette window we’ll see a row of painting tools that will let us add, erase and edit tiles on the tilemap. There will also be an area where existing tiles are available to be selected. We’ll be able to select tiles from the Palette, then paint them directly on the map with the tools available.
But first we need some tiles to paint. You can use any tiles or sprite you have handy. For this article I’m using a Rogue-like tileset called Loveable Rogue, available from here, which I’ve trimmed down. To prepare the texture, we will need to
- Import the texture into Unity
- Change the sprite type to multiple
- Use the Sprite Editor to splice up the texture
Once we have the texture sliced up all we have to do is drag it on the the Tile Palette. We’ll first have to create a palette from the top left of the window. During this process you will be asked to name, then save the Palette asset.
Once we have that, all we have to do is drag the sliced texture on to the palette. At this point a couple things will happen that confused me the first time I did it, so lets walk through what happens
First, when you drag the texture onto the palette you will get an outline with the size of the Texture. The palette can be customized at will, you can move tiles around the palette, allowing you to group similiar objects together for easy access. Later on this box will matter if you want to avoid overwriting existing tiles on your palette, but since ours is empty we can just drop it anywhere.
Second you will get a popup asking for a folder. Under the folder selected, Unity will create a new asset for every Sprite in the texture. Since this could be a very large number of tiles, I created a separate folder to store them all.
Once you click okay Unity will start processing the texture, creating all the necessary Tile assets in the folder. Once that’s done, we can start adding tiles to our tilemap.
Just select the Paint with Active Brush option at the top (third from the left), select a tile from the Palette, and go to down adding tiles to your tilemap in the Scene window.
Pretty neat huh? We’ve just scratched the surface with what Tiles and Tilemaps can do in Unity, but lets take a step back to take a look what is going on with the tilemap we already have.
I think the most important thing to understand about Tilemaps in Unity is that TILES ARE NOT GAMEOBJECTS.
Let me repeat that 1 more time because I think it’s that important to understanding everything else going on. TILES ARE NOT GAMEOBJECTS.
A GameObject does not get created for every tile in your tilemap (which is VERY good for large maps). You cannot add components or scripts to Tiles. You can verify this by adding a bunch of tiles to your tilemap then running the game. Look in the inspector. There’s just the Grid and Tilemap from before. Nothing gets created for the tiles.
So, if they’re not GameObjects, what are they? They’re Sprites. Ordinary Sprites, just a visual component, nothing that can interact with the rest of the world. However the way Tiles are created gives them a unique twist. A twist that makes the much more powerful from ordinary sprites, without incurring the overhead of creating a GameObject for every tile (some of the 3rd party extensions I tried in the past created a GameObject for every Tile. It works okay for small maps, but I found it gets way too slow on larger maps).
Lets take a look at the folder where Unity created all the Tile assets. You might have assumed (like I did) that Unity created a Prefab under here for each tile. But if we click the tiles we can clearly see they are not Prefabs. So what are they? They’re ScriptableObjects, a type of Unity assets that are very powerful, but often not discussed enough in my opinion. Going into ScriptableObjects is outside the scope of this article, but if you’re not familiar with them, I encourage you to read the previous link before continuing.
The Tile assets don’t derive directly from ScriptableObject though, they derive TileBase, a class which all Tiles must inherit from. TileBase defines the methods that allow a Tile to be customized in different ways. TileBase has a few responsibilities:
- Defining what a tile looks like
- Once placed, determining if any neighbors need to be updated
- Initializing the tile
Once the tile has been created in the map, TileBase does nothing else unless it is asked to update it’s visual representation. TileBase doesn’t get updated every frame, it’s only invoked when needed.
And something else important to keep in mind, an instance of TileBase is not created for every tile. Instead the same class is reused for every tile of that type, so do not use TileBase to store Tile instance data. The methods on TileBase can be called multiple times, each with a different tile.
So, if all TileBase does is determine what a Tile looks like, what is the point? Why not just reference Sprites directly.
Consider the below tiles from the Loveable Rogue tileset I was using earlier. They are all ‘Wall’ tiles, but they all look a little differently. Some are straight, some are corners, and some are intersections. But at the core they are all ‘Wall’ tiles. If we were building a complex dungeon, it would take a very long time to hand place each tile because we’d need to keep switching back and forth in the Palette. If would be much easier if there were something could change the look of the tile based on what it’s neighbors were.
That something is TileBase. The methods in TileBase let us do just that. We can define a single ‘Wall’ class that inherits from TileBase, and takes all the different wall sprite variations as input. When the ‘Wall’ tile is asked to define what it looks like, it can query the existing map, look for neighbors, and select the appropriate variation. Is it all alone? Return the single wall tile. Is it at a T-intersection? Return the appropriate T-intersection variation.
Not only that, but it can also tell neighbors to update as well. If we place a single wall, then place another, the first needs to change it’s appearance in response.
Once this ‘Wall’ class is defined, we can add it to our Palette and start painting walls, and as we do so, we can see them change in response to the other tiles around them. I won’t be going into that in this article, but Unity has an awesome sample on Github that demonstrates the power of TileBase.
Unity has documentation for Tilemaps on their website , which is well worth reading through. But something else I highly recommend doing is taking a look at the 2d-extras repository Unity has published on github. There are several good example of Tilemaps on there, ones that go beyond the basics and really display the power the Tilemap feature has. I spent evening playing around with the examples, and reading through the code to understand how everything worked. Seeing these features in use is a great way to learn how it works.
Up next, creating minesweeper
That’s it for this article. I hope you find the new Tilemaps as exciting as I do, and hopefully have bit clearer picture of what they are, and how they work.
In the next article, I will take a look at modifying Tilemaps programmatically from scripts, then use that to create a full Minesweeper game.