Skip to content

Tile Prefabs

A tile can carry a prefab that is instantiated wherever the tile is painted: a chest, a torch with a light, a door with its own script. This page covers what the tilemap does with that prefab and how your scripts find out which cell created them.

Concept

The prefab is set per tile in the Tile Properties window and stored in Tile.prefabData, a TilePrefabData. Every time a cell is written with that tile, the tilemap instantiates the prefab, places it on the cell, and sends the new object the message OnTilePrefabCreation. Erasing or overwriting the cell destroys the object.

Instances are parented to the tilemap's GameObject, not to a chunk, so you see them in the hierarchy under the tilemap. In the editor they are created with PrefabUtility.InstantiatePrefab and keep their prefab link, and painting them is undoable. In a build they are plain Instantiate copies.

How the instance is placed

Step Source
Position The centre of the cell, plus offset. With offsetMode set to Pixels the offset is divided by the tileset's pixels per unit; with Units it is used as is. The z comes from the prefab's own position.
Rotation The prefab's local rotation, then rotation as Euler angles.
Scale The prefab's local scale.
Tile flags Rot90 turns the object 90 degrees clockwise about the tilemap's forward axis. FlipH and FlipV together turn it 180 degrees. A single flip negates the scale on that axis.

The tile itself is not drawn under the prefab unless showTileWithPrefab is set. That is the Show Tile With Prefab toggle in the Tile Properties window.

Receiving OnTilePrefabCreation

Add a method with this signature to a component on the prefab's root GameObject:

void OnTilePrefabCreation(TilemapChunk.OnTilePrefabCreationData data)

The message is sent with SendMessage, which only reaches components on the root, not on children.

TilemapChunk.OnTilePrefabCreationData carries:

Member What it is
ParentTilemap The STETilemap that created the object.
GridX, GridY The cell, in tilemap grid coordinates.
Tile The Tile at that cell. Looked up when you read it.
Brush The TilesetBrush at that cell, or null.
Parameters The brush's parameters if the cell has a brush, otherwise the tile's. May be null.

An example that reads a tile parameter into the instance:

using UnityEngine;
using CreativeSpore.SuperTilemapEditor;

public class Chest : MonoBehaviour
{
    [SerializeField] private int m_gold;
    private STETilemap m_tilemap;
    private Vector2Int m_cell;

    public int Gold => m_gold;

    void OnTilePrefabCreation(TilemapChunk.OnTilePrefabCreationData data)
    {
        m_tilemap = data.ParentTilemap;
        m_cell = new Vector2Int(data.GridX, data.GridY);

        ParameterContainer parameters = data.Parameters;
        if (parameters != null)
            m_gold = parameters.GetIntParam("gold", 10);
    }

    public void Open()
    {
        // Remove the chest tile. This instance is destroyed at the next rebuild.
        m_tilemap.Erase(m_cell.x, m_cell.y);
        m_tilemap.UpdateMesh();
    }
}

The message can arrive more than once for the same object. Writing the same tile to its cell again, or calling Refresh with refreshTileObjects set, keeps the existing instance, puts it back in place and sends the message again. Make the handler safe to repeat.

It is also sent in edit mode while you paint. If your handler must run there, mark the component [ExecuteAlways], as TileObjectBehaviour is.

TileObjectBehaviour

TileObjectBehaviour is a ready-made receiver. Put it on a prefab with a SpriteRenderer, and when the prefab is created from a tile it sets the renderer's sprite to that tile's image, at the tilemap's pixels per unit. Unless Change Sprite Only is ticked, it also copies the tilemap's sorting layer and order in layer.

That turns any tile into a separate GameObject that looks like the tile. One prefab can stand in for every crate, barrel or sign in the tileset, and each instance can have its own collider, rigidbody or script.

OnTilePrefabCreation is protected virtual in TileObjectBehaviour, so you can extend it:

using UnityEngine;
using CreativeSpore.SuperTilemapEditor;

public class BreakableTile : TileObjectBehaviour
{
    [SerializeField] private int m_hitPoints = 3;

    protected override void OnTilePrefabCreation(TilemapChunk.OnTilePrefabCreationData data)
    {
        base.OnTilePrefabCreation(data);
        m_hitPoints = TilemapUtils.GetTileParameter(data.ParentTilemap, data.GridX, data.GridY, "hitPoints", m_hitPoints);
    }
}

For a receiver that is not a TileObjectBehaviour, the static TileObjectBehaviour.DoOnTilePrefabCreation(data, spriteRenderer, changeSpriteOnly) does the sprite work for any SpriteRenderer you pass, and TileObjectBehaviour.GetOrCreateSprite(data) returns the sprite alone. Both cache sprites, one per tile and pixels per unit.

Finding the instance of a cell

GameObject obj = tilemap.GetTileObject(gridX, gridY);

It returns null when the cell has no prefab instance.

Generating a map with tile prefabs

Instances are created inside SetTileData, at the moment of the write, not at the next rebuild. A generator that writes a cell several times, or clears and regenerates, pays for an instantiate and a destroy every time. Switch creation off while you generate and create all the instances once at the end:

STETilemap.DisableTilePrefabCreation = true;
try
{
    GenerateLevel(); // your SetTile calls
}
finally
{
    STETilemap.DisableTilePrefabCreation = false;
}
// Create the instances for the final map, then rebuild.
tilemap.Refresh(false, false, true, false);

DisableTilePrefabCreation is static and affects every tilemap, which is why the finally matters. Play mode entry resets it to false.

While it is on, overwriting a cell also leaves its old instance in place. The Refresh call at the end removes instances whose cell no longer holds a tile with a prefab, and creates the missing ones.

Destroying is deferred: an object whose cell was overwritten is removed at the next rebuild of its chunk. ClearMap destroys every child of the tilemap right away, instances included.

Reference

TilePrefabData fields, as stored in each Tile:

Field What it does
prefab The prefab to instantiate. null means no prefab.
offset Offset from the cell centre.
offsetMode Pixels or Units, the unit of offset.
rotation Extra rotation, in Euler angles.
showTileWithPrefab Draw the tile under the prefab instance too.
showPrefabPreviewInTilePalette Show the prefab's preview in the tile palette instead of the tile.