Cristian C.
Cristian C.

Reputation: 828

Per Tilemap Tile Data Storage & Retrieval

I have a scenario where I will need to know certain information about all of the tiles in a tilemap. From the research I've done and questions that others have had, this may not be the easiest thing to do.

I am faced with 3 possible options, as far as I can tell:

  1. Don't use Unity's Tilemap, and build the tiles out by hand instead via a list of GameObjects and sprites. Then attach any sort of model I may need with custom values as a script to said GO. This will make it very simple to add logic to each tile. The downsides will be that it'll be a lot more annoying to build out maps.

  2. Use Unity's Tilemap, but keep track of each special node tile in code manually. Needless to say, this isn't a very attractive workflow, since any time the map changes, the change would have a need to reflect in the code map/list/array

  3. Override Unity's Tiles (just like the 2d extras pack) and creates a rule tile for every special tile. When reading in the tiles, and compiling a dictionary, check the type of tile and assign any special properties based on the type of tile you're currently looking at. The rule tiles can either be visual tiles or painted on a tilemap underneath the visual tilemap used only for storing information of the map above it.

  4. (3.1) Do the same as above, but instead of using special rule tiles, separate any special tiles onto their own special Tilemaps. Then read through each tilemap and compile a dictionary that keeps track of any special tiles and their special properties.

Currently I am using the following:

private void GetWorldTiles ()   { 
    tiles = new Dictionary<Vector3, WorldTile>();       
    foreach (Vector3Int pos in Tilemap.cellBounds.allPositionsWithin)       {
        var localPlace = new Vector3Int(pos.x, pos.y, pos.z); 
        if (!Tilemap.HasTile(localPlace)) continue;
        var tile = new WorldTile
        {   
            LocalPlace = localPlace,
            WorldLocation = Tilemap.CellToWorld(localPlace),
            TileBase = Tilemap.GetTile(localPlace),
            TilemapMember = Tilemap,
            Name = localPlace.x + "," + localPlace.y,
            Cost = 1 // Cost is needed for pathfinding. Other properties may also exist such as "isSpawnPoint", or what have you.
        };                      
        tiles.Add(tile.WorldLocation, tile); //tiles is a Dictionary<string, WorldTile>
    }
}

The above code is lifted from this short tutorial here

The contents of my maps are going to be semi random. For example, the player characters will have dedicated spawn points per map, but enemy characters will spawn randomly on any tiles they are allowed to spawn on. Some tiles will also spawn things like treasure chests, and other tiles will have special properties such as water tiles only being traversable by water units, etc.

For now, this is what a simple map looks like, with all sprites as placeholders. Simply put, the hex tiles are obstacles, and the X tiles are walls that are also unpassable, showing the border of the map (final product map size may vary)

Simple Example Tilemap

The game will use a breadth first search algorithm to allow tactics-style turn-based movement, so it's paramount that I know which tiles are going to be obstacles for one reason or another.

If you have any questions, I'd be happy to answer them.

Additional Info

I also see that Tiles have reference to a gameObject property, but I haven't seen any examples of this being used.

Upvotes: 1

Views: 2523

Answers (1)

Ben Rubin
Ben Rubin

Reputation: 7341

You could have one layer in your tilemap for each type of base terrain, and attach a script to each terrain layer that specifies what types of units are allowed to enter tiles that are part of that layer. Some spaces may have overlapping tile layers. Mountains, for example, might have a "land" tile and a "mountain" tile.

Then when you're doing your pathfinding calculations, you only consider spaces that have at least one tile (to prevent units moving off the map) and that the unit type is allowed to enter each type of tile that is on that space. Something like this:

public class TerrainLayer : MonoBehaviour
{
    public bool canAirUnitsEnter;
    public bool canLandUnitsEnter;
    public bool canSeaUnitsEnter;
}

enter image description here

enter image description here

enter image description here

enter image description here

enter image description here

Upvotes: 1

Related Questions