1
votes

I'm trying to use the new Unity Tilemap introduced in Unity 2017.2 but I'm struggling a bit and wondering if it's worth bothering with. The documentation is a bit thin and examples are lacking. I am making a top down old school RPG and would love to use the new Tilemap features but I've run into a couple issues:

Firstly, as far as I can tell there is no visibility of the individual tile's 'gameObject'. According to the documentation, each tile has it's own 'gameobject' (typo? should be gameObject?). I'm still a bit confused if this is simply the parent gameObject or the tile's 'Instanced Game Object'. The 'Instanced Game Object' for a given tile does show up in the inspector if you click on the tile in the scene but there doesn't seem to be a way to adjust its transform (either in code or inspector) so it's very inflexible. What is the common use case for a tile's instanced game object?

In my game I am making a farming sim where some tiles would be 'tillable' so I thought this new tilemap feature would be a perfect opportunity to try out a new scriptable tile but I could not figure out how to use it properly with the current documentation. I want the tiles to change sprites based on other tiles around them but I struggled to get that to work properly. There is a similar example in the documentation and I believe I could get it working if I spent some more time but even if I did get that working it appears I would have other blockers - each tile is lacking hooks into the normal Unity gameObject lifecycle - Start() OnEnable() OnDisable() etc... So I would have no way to script the tile as I would need. I'm not sure if there is a way around this other than creating a new public game object on the tile and simply scripting that game object to do what I need. If I have to do that, the tilemap feature is basically doing nothing for me and I might as well just add those tiles as game objects myself to the scene. Also, it'd be worse because I cant even see individual tiles easily in the scene inspector. And I also don't believe I'd be able to adjust their transforms.

Has anyone else encountered these issues and is there a guide out there I can read for how to get started using the new Tilemap features?

2
BTW you may want to ask for this to be migrated to [GameDevelopment]Stephan

2 Answers

1
votes

I agree that examples are thin right now, but this is a feature that you definitely want to get to know.

For one, the tilemap is rendered as a single mesh with each quad textured to whatever you've programmed it to be. This is extremely efficient, and allows much larger maps than you'd be able to achieve with individual game objects for each tile.

Check out the tech demos for tile map on git. There are examples of road tiles, animated tiles, pipe tiles, etc. They should be able to get you started. When I get off work I'll write up the road tile example, as that's the one which most directly fits how you intend to use them.

https://github.com/Unity-Technologies/2d-extras/tree/master/Assets/Tilemap/Tiles

0
votes

I had the same question, and after some googling and reading about it I wrote a script that does what we want :)

Your tileset must have 7x7 tiles and look like that (you probably understand the idea of how it works):

Tileset 49 sprites 0-48

Here's the code:

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

#if UNITY_EDITOR
using UnityEditor;
#endif

public class BitmaskTile49 : Tile
{
    public Sprite[] sprites;
    public Sprite previewSprite;

    public Dictionary<int, int> maskIndex = new Dictionary<int, int> () {
        { 0, 0 },
        { 4, 1 },
        { 92, 2 },
        { 124, 3 },
        { 116, 4 },
        { 80, 5 },
        // { 0, 6 },
        { 16, 7 },
        { 20, 8 },
        { 87, 9 },
        { 223, 10 },
        { 241, 11 },
        { 21, 12 },
        { 64, 13 },
        { 29, 14 },
        { 117, 15 },
        { 85, 16 },
        { 71, 17 },
        { 221, 18 },
        { 125, 19 },
        { 112, 20 },
        { 31, 21 },
        { 253, 22 },
        { 113, 23 },
        { 28, 24 },
        { 127, 25 },
        { 247, 26 },
        { 209, 27 },
        { 23, 28 },
        { 199, 29 },
        { 213, 30 },
        { 95, 31 },
        { 255, 32 },
        { 245, 33 },
        { 81, 34 },
        { 5, 35 },
        { 84, 36 },
        { 93, 37 },
        { 119, 38 },
        { 215, 39 },
        { 193, 40 },
        { 17, 41 },
        // { 0, 42 },
        { 1, 43 },
        { 7, 44 },
        { 197, 45 },
        { 69, 46 },
        { 68, 47 },
        { 65, 48 }
    };

    public override void RefreshTile (Vector3Int location, ITilemap tilemap)
    {
        for (int y = -1; y <= 1; y++) {
            for (int x = -1; x <= 1; x++) {
                Vector3Int nextLocation = new Vector3Int (location.x + x, location.y + y, location.z);

                if (HasBitmaskTile (nextLocation, tilemap)) {
                    tilemap.RefreshTile (nextLocation);
                }
            }
        }
    }

    public override void GetTileData (Vector3Int location, ITilemap tilemap, ref TileData tileData)
    {
        int north   = HasBitmaskTile (location + Vector3Int.up, tilemap) == true ? 1 : 0;
        int west    = HasBitmaskTile (location + Vector3Int.left, tilemap) == true ? 1 : 0;
        int east    = HasBitmaskTile (location + Vector3Int.right, tilemap) == true ? 1 : 0;
        int south   = HasBitmaskTile (location + Vector3Int.down, tilemap) == true ? 1 : 0;
        int northwest   = HasBitmaskTile (location + Vector3Int.up + Vector3Int.left, tilemap) == true ? 1 & north & west : 0;
        int northeast   = HasBitmaskTile (location + Vector3Int.up + Vector3Int.right, tilemap) == true ? 1 & north & east : 0;
        int southwest   = HasBitmaskTile (location + Vector3Int.down + Vector3Int.left, tilemap) == true ? 1 & south & west : 0;
        int southeast   = HasBitmaskTile (location + Vector3Int.down + Vector3Int.right, tilemap) == true ? 1 & south & east : 0;

        int mask = 1 * north + 2 * northeast + 4 * east + 8 * southeast + 16 * south + 32 * southwest + 64 * west + 128 * northwest;
        mask -= mask > 255 ? 256 : 0;

        tileData.sprite = sprites [maskIndex [mask]];
    }

    public bool HasBitmaskTile (Vector3Int location, ITilemap tilemap)
    {
        return tilemap.GetTile (location) == this;
    }

    #if UNITY_EDITOR

    [MenuItem ("Assets/Create/Bitmasking/Bitmask Tile 49")]
    public static void CreateRoadTile ()
    {
        string path = EditorUtility.SaveFilePanelInProject ("Save Tile Bitmask 49", "New Tile Bitmask 49", "Asset", "Save Tile Bitmask 49", "Assets");
        if (path == "")
            return;
        AssetDatabase.CreateAsset (ScriptableObject.CreateInstance<BitmaskTile49> (), path);
    }

    #endif
}

And that's the result: Example of how it looks

For more info you can check the place I got the concept from: http://www.cr31.co.uk/stagecast/wang/blob.html