2D Tilemap Asset Workflow: From Image to Level
In Unity 2017.2, we introduced a new addition to the 2D Feature Set: Tilemaps! Using Tilemaps, you can quickly layout and create 2D levels using a combination of Sprites and GameObjects, and have control over properties such as layer ordering, tilemap colliders, animated tiles and more! In this blogpost, I will explain the full workflow beginning at importing your image file into Unity all the way through to a laid out level for a 2D Platformer!
As a TL;DR overview; the workflow can be summarised like this, with each element relating to an Asset or a Component in the Unity Editor:
Sprite -> Tile -> Palette -> Brush -> Tilemap
From a Non-Unity point of view, these terms could seem a little abstract. Just imagine the process for a real-life painting on a real-life canvas:
Color -> Paint -> Tile Palette -> Paint Brush -> Canvas
There is similar logic to each step of the process and even similar names for each step!
For this post, I will use this ‘GrassPlatform_TileSet’ Image as the main example:
With the end result being a level constructed of these pieces that a 2D character can run on as a ‘level’:
Importing an Image into Unity can be done in a variety of ways:
— Saving the desired Image file into the project’s ‘Assets’ folder.
— From the top menu, selecting ‘Assets -> Import New Asset’ and then selecting the desired file.
— Dragging the Image File from your File Browser into the ‘Project Window’ in the Unity Editor (This is probably the easiest way!)
Once the image is imported into your project, its default Texture Type import settings are defined by which behaviour mode your project is currently set to: 2D or 3D.
This mode is originally set when a new project is created:
Or can be changed from in Editor Settings:
As my project already is setup for 2D Behaviour Mode, then ‘GrassPlatform_TileSet’ will automatically import with the Texture Type of ‘Sprite (2D and UI)’ which is the setting that the Tile asset will require to reference the Sprite.
As the ‘GrassPlatform_TileSet’ is a series of sprites in one image, we will need to slice it into individual sprites; this can be done by setting the Sprite Mode from ‘Single’ to ‘Multiple’ and opening the Sprite Editor:
The Sprite Editor window allows you to ‘slice’ an image into multiple sprites; so you can work on one spritesheet in your desired image editing software and define which areas of the image are treated as ‘individual’ sprites directly in Unity. No need to juggle and manage hundreds of individual image files!
As ‘GrassPlatform_TileSet’ is an image composited of a series of tiles, we can use the Sprite Editor’s Grid Slicing Settings to automatically split the image into multiple sprites. The dimensions of each ‘cell tile’ in this tileset are 64 pixels by 64 pixels, so we can input these setting and let the Sprite Editor auto-generate the required sprite slices:
And after the ‘Slice’ button is clicked, we now have a sliced set of sprites!
In the Sprite Editor window, each sliced sprite is then selectable and editable. For example, you can set names for each sprite and even manually tweak values such as position and pivots.
We then need to ‘Apply’ the changes to the Sprite Asset (by clicking the aptly named ‘Apply’ button near the top-right corner of the Sprite Editor) which will then allow us to reference each sliced sprite individually in the Project window:
Now that our Sprite Sheet has been sliced into individual Sprites, we next need to ‘convert’ these into Tiles.
2) Tile Asset
The Tile is a brand new asset added in Unity 2017.2. Its purpose is to hold data for the Tilemap to use at a specific cell on the grid.
The base default Tile asset (which can be generated from ‘Create -> Tile’ in the Project window) allows for a Sprite to be assigned to it and also other customisations such as the Tint of the Sprite and the type of Collider that it would use on the Tilemap (which will be explained later).
3) Tile Palette Window
Unity 2017.2 introduces a new window: the Tile Palette! This window is integral to using the new Tilemap system as it acts as an interface to select which Tiles to use and how the Tilemap is to be edited with them.
Before we can add the ’TopGrassTile’ Tile to the Tile Palette window, we first need to create a new Palette. Palettes can be used to organise your sets of Tiles instead of ‘storing’ all of them (could be hundreds or more!) on to one workspace in the window.
In the drop-down Palette menu there is an option to create a brand new Palette:
It’s as simple & easy as drag-and-drop to add ‘TopGrassTile’ to this newly created Palette!
However, in some situations we might be working with hundreds and hundreds of Sprites that build up our 2D scene. It would be very time-consuming to manually create a Tile asset for each of these Sprites and then drag-and-drop each one individually onto the Palette.
Thankfully, there is a workflow that can be used to automatically generate a set of Tiles (one for each Sprite) and assign all of them to the desired Palette. And it‘s also as simple & easy as drag-and-drop! Instead of dragging a Tile asset onto the Palette, drag the source Spritesheet that contains the sliced Sprites. In this case, ‘GrassPlatform_TileSet’:
4) Grid & Tilemap
Now that our ‘GrassPlatform_TileSet’ spritesheet is successfully set up in the Tile Palette window, it’s time to start constructing a 2D Level!
To begin, we need to can create a brand new ‘Tilemap’ in our current scene; this can be done from the ‘GameObject -> 2D Objects -> Tilemap’ drop-down menu. However, this not only creates a ‘Tilemap’ GameObject (With related components) but also a ‘Grid’ GameObject that the Tilemap gameObject is automatically a child of.
The most similar GameObject structure to the ‘Grid <-> Tilemap’ setup is Unity’s UI System; where the Canvas parent GameObject acts as a layout container for all of its child UI GameObjects (Such as Text and Images). The ‘Grid’ GameObject uses the ‘Grid’ Component to define the dimensions of all of its child Tilemap GameObjects. There are options that allow for some customisation in the layout:
The child Tilemap GameObject is then constructed by both the Tilemap component and the Tilemap Renderer component; the former containing the data of the Tiles painted onto it and the later defining the visual settings of how it is rendered.
The Tilemap system has been designed so that multiple Tilemap GameObjects can be children of the same Grid, meaning that the end result of your level can be easily composited by multiple layers of different Tiles:
Each Tilemap Renderer gives you control over the Material used to render its Tiles, the Sorting Layer it uses (which is the same layer system that Sprite Renderers, UI Canvases and Particle Systems use!) and also how it reacts to the Sprite Mask.
5) Painting onto the Tilemap
Before Tiles can be painted onto the Tilemap, two things have to be selected: which Tilemap is currently focused and which Brush is currently in use.
This drop-down list will show all instances of the ‘Tilemap’ component in the scene and will allow you to select one to be painted on and edited. The above screenshot only shows one ‘Tilemap’ option, and named after the default Tilemap GameObject, whereas a more complex scene with multiple Tilemaps could display a list of possible Active Tilemaps such as this:
For the ‘GrassPlatform_TileSet’ example, renaming the “Tilemap’ GameObject to be more accurate will also update the Active Tilemap list name(s):
The next thing to select is the current Brush. Whilst the Tile asset determines what data a cell would contain (Visuals, Collider Type, etc), a Brush asset defines how a Tile (or Tiles) would be placed onto a Tilemap. Currently, Unity only has one Brush (named ‘Default Brush’) built-in to be selected; and it has expected functionality of its name such as placing, erasing, moving and filling Tiles on the Tilemap. However, on the Unity Technologies Team GitHub there is a 2D Extras’ Repository that has a variety of examples of how you can script your own custom Brushes and Tiles! Once these are imported into your project, the current Brush menu (at the bottom of the Tile Palette window) will allow you to choose which Brush to use:
Whilst this article doesn’t dive into the use of Scriptable Brushes and Scriptable Tiles, it’s a very powerful area to study and integrate into your tilemap-based level-design toolset.
With the Active Tilemap and Current Brush set, we can then select a specific Tile, in the Tile Palette window, and then paint it onto the Tilemap in the Scene! You will also need to make sure that the ‘Paintbrush’ Icon in the Edit Tools is also selected:
Success! Tiles are being painted on the Tilemap! However, you may notice that the Tiles are slightly smaller than the size of the Grid’s cells. This is not a bug, but we need to step back a bit for some explanation of why — and how you can change the default.
The Grid component’s Cell Size uses Unity’s world space distance units (For example, a primitive Unity cube with default scaling of 1 for each axes will be the same size as one cell on the default Grid). Each Sprite asset has a Pixels Per Unit value in its Import Settings, with the default value being 100:
As each of ‘GrassPlatform_TileSet’s sprites has a dimension of 64 pixels by 64 pixels, setting the Pixels Per Unit value accordingly will automatically adjust the scale of all instances of the sliced Sprites; thus fitting the related Tiles accurately into the Grid’s Cells!
And now we can begin to create our Tilemap level using the various Editing Tools at the top of the Tile Palette window.
It’s worth noting that it’s also possible to select a range of multiple Tiles in the Tile Palette and paint them together as a group:
6) Tilemap Collider & Composite Collider
Now you have all the knowledge needed to manually paint a basic level such as this:
However, if you add a physics-driven 2D Character and enter Play Mode, they would, by default, fall through the ground platform. Thankfully, Unity 2017.2 also introduces the very useful Tilemap Collider 2D component, which, when applied to a Tilemap GameObject, will auto-generate a Collider around the Tiles (Based on the Tile’s Collider Type Setting).And in Play Mode, our 2D Character can run and jump on the Tilemap!
Another useful component that was added to the 2D Physics Toolset is the Composite Collider. Adding this to the Tilemap Collider 2D will merge all of the Tile’s Colliders into one much more optimised geometry collider mesh!
And the last tweak we can make is to Offset the Tilemap Collider in the Y Axis. This will lower the Collider so that it looks as though the 2D Character is running along the grass platform as opposed to floating directly above it:
And that concludes this tutorial on the Tilemap asset and component workflow; from Image File to a basic constructed level that has an automatically-generated collider!
There are many more areas to cover for the Tilemap System; for some more information I would recommend watching Matt Schell’s Live Training Video on 2D World Building.
However, if there are other topics that you would be interested in a deep-dive blogpost about, such as Scriptable Brushes, Scriptable Tiles, Animated Tiles, Rendering and Ordering Multiple Tilemaps etc, then please leave a comment below!