Unity multi-layer 2D tilemap


Overview

In this post, we try to implement a unity 2D tile map with two layers. The first underlying layer should include tiles representing the geographical/natural/physical composition of the map, with tiles like sea, forest, desert, mountain, … tiles. The second layer should include tiles representing empires. Each empire with a different color.

We have first to create these two tilemap layers and then find a way that allows the player to switch between the two layers when the game is running.

We also would like an additional function that would allow the player to make the empire layer a bit transparent so that the player could see the underlying physical layer.

To achieve these requirements we can follow these steps:

  • Create the two tilemaps. You can basically follow the same steps as described here to achieve this: Unity 2D tilemaps
  • In the Inspector for the second tilemap, set the [Sorting Layer] property to a value higher than the first Tilemap’s sorting layer. This will ensure that the empire tiles are rendered on top of the physical tiles.
  • To allow the player to switch between the two layers during runtime, you can use a simple script that toggles the visibility of each tilemap component.

Creating and preparing the tile maps

We create two tile maps, the physical map and the map of the empires (you can see here how to do this: http://www.iteacorner.com/unity-2d-tilemaps/)

To make sure that the physical map is below the map of the empires, we have to set its [Order in Layer] to a smaller value e. g. -5:

Here we have created two tile maps (PhysicalMap & EmpiresMap). Each map has its own tile palette that can be selected with a drop-down in the [Tile Palette] window. The EmpiresMap is made a bit transparent using the [Color] tool in the [Inspector] window.

A button that switches the tile maps

Next, we want to add a button that is always visible, which allows the player to switch between the maps. The button can be important if we want to see the map of the empires fully and not transparent but also to make it clear whether we want to do some interaction involving the physical map or the map of the empires, so basically we want to define which map is the currently active map.

To add such a button, we must first add a canvas to our hierarchy. Right-click on the [Hierarchy] window and then select [UI –> Canvas]:

Double-click on the newly created Canvas object to see the Canvas view:

Add a button to canvas: Right-click Canvas and then select [UI –> Button – TextMeshPro]:

At this point, you might encounter the following message:

You might also have missed it because it might appear somewhere on the bottom like this:

But you must confirm this and click on [Import TMP Essentials] otherwise, your added button might not work properly. For example, in my case, the button was added but was never showing any text and I had no clue that this was because I hadn’t clicked on [Import TMP Essentials] when that message was shown to me.

If the button was added correctly to the canvas you should see something like this: An empty canvas with a button with a default text. If the text is missing you have probably forgotten to click on that import button mentioned above:

We want everything on the canvas to be always visible (on top of the tile maps): Make sure that the option [Render Mode] is set to [Screen Space – Overlay] in the [Inspector] window for canvas:

If we would start our game in the current state, we will see the button in the middle of our time maps. But we prefer the button to be on the top left. To move the button, select the button (1) in the [Hierarchy] window, select the button in the canvas (2), select the move tool (3), and then drag and drop the button (4) using the green or the red arrow or the small blue square:

Select the button and modify the button’s caption text in the [Inspector] window, in the [Text Input] field:

If you have to change the size of the button, so that the text matches inside the button: Click on the [Rect Tool] (1) and then resize the button (2):

You can adjust the color of the button in the [Inspector] window:

Now if you run the game (by switching to the [Game] tab (1) and clicking on the run button [2]), you can see the button on the top left:

Right now the button does nothing, so we have to add a script to that button that switches the current tile map (between PhysicalMap and EmpiresMap).

Click on the canvas item on the [Hierarchy] window, click on the [Switch the map] button (1), and on the [Inspector] windows click on [Add Component] (2):

Select the option [New script]:

Enter the name for the script e. g. “MapSwitcher”:

The new script appears in the [Assets] window:

Open the “MapSwitcher” script in your preferred code editor by clicking on the script in the [Assets] window (1) and then on [Open] button in [Inspector] window:

The script opens in the pre-configured editor (e.g. Visual Studio). Add the following variables at the top of the script:

public Tilemap map1;
public Tilemap map2;
public bool isMap1Active = true;

This will allow you to reference the two tile maps in the script, and keep track of which one is currently active.

In the “MapSwitcher” script, add the following code:

public void OnSwitchMapButtonClick() {
    if (isMap1Active) {
        map1.gameObject.SetActive(false);
        map2.gameObject.SetActive(true);
        isMap1Active = false;
    } else {
        map1.gameObject.SetActive(true);
        map2.gameObject.SetActive(false);
        isMap1Active = true;
    }
}

So at this stage, the full script would look like this:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Tilemaps;

public class MapSwitcher : MonoBehaviour
{
    public Tilemap map1;
    public Tilemap map2;
    public bool isMap1Active = true;

    public void OnSwitchMapButtonClick()
    {
        if (isMap1Active)
        {
            map1.gameObject.SetActive(false);
            map2.gameObject.SetActive(true);
            isMap1Active = false;
        }
        else
        {
            map1.gameObject.SetActive(true);
            map2.gameObject.SetActive(false);
            isMap1Active = true;
        }
    }
}

This method will be called when the “SwitchMap” button is clicked and will switch between the two tile maps but we need to configure the event that is supposed to be handled by this event handler.

In the Unity editor, select the [Switch the map] button, and go to the [Inspector] window. Click the [+] button below the [On Click ()] event field to add a new event:

Drag and drop (1) the [Canvas] element that contains the button to the field left of the entry that was added after clicking on the plus button (see above). Then select (2) the method OnSwitchMapButtonClick() in the drop-down on the right side.

Testing the application

Switch to [Game] tab and then click on the play button. The game starts. Now you can switch between the physical map and the map of the empires by clicking on the [Switch the map] button:

Of course, because we configured the empires map to be a bit transparent, we could also have the physical map always visible (by removing the lines changing its visibility), and then clicking on the [Switch the map] button would only hide and show the map of the empires on top of the physical map:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Tilemaps;

public class MapSwitcher : MonoBehaviour
{
    public Tilemap map1;
    public Tilemap map2;
    public bool isMap1Active = true;

    public void OnSwitchMapButtonClick()
    {
        if (isMap1Active)
        {
            map1.gameObject.SetActive(false);
            map2.gameObject.SetActive(true);
            isMap1Active = false;
        }
        else
        {
            map1.gameObject.SetActive(true);
            map2.gameObject.SetActive(false);
            isMap1Active = true;
        }
    }
}

Adjusting the transparency with a slider

Another feature that could be useful in connection with multiple layers would be the ability to change the transparency of a layer in runtime. For example, we can add a slider to the GUI that can be used to change the transparency of the second layer (map of the empires).

To do that right-click on Hierarchy window and select [UI –> Slider]:

The slider will be added to the Canvas:

Add a script to the assets. Right-click on the Assets windows and select the option [Create –> C# Script]:

Click on the created script and open it in your favorite editor for editing:

Update the code of the script as follows:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Tilemaps;
using UnityEngine.UI;

public class OpacitySlider : MonoBehaviour
{
    public Tilemap tilemap;
    public float opacityValue;

    void Update()
    {
        tilemap.color = new Color(tilemap.color.r, tilemap.color.g, tilemap.color.b, opacityValue);
    }

    public void UpdateOpacity()
    {
        opacityValue = GetComponent<Slider>().value;
    }
}

Select the Slider object (1). Add a new event under [On Value Changed (Single)] by clicking on the plus button there (2). Drag and drop (3) the Slider from the [Hierarchy] window to the field left in the added entry. Select the method ObacitySlider.UpdateOpacity() (4):

Now you can change the opacity of the second layer (if it’s selected) using the slider: