Search Unity

Question Individual Tile handling within Tilemaps

Discussion in '2D' started by AdamLacko, Mar 20, 2022.

  1. AdamLacko

    AdamLacko

    Joined:
    Oct 10, 2017
    Posts:
    41
    Hi,

    I work as a freelancer for a game studio and we're prototyping a 2D isometric RPG, very similar to classic Fallout titles. In fact, we're trying to build fairly precise equivalent of the original engine/technology used in classic Fallout titles witin Unity.

    Unlike many tile-based 2D games, our game (just like classic Fallout games) is supposed to use tiles that are not shaped after the placement grid. Tile placement and gameplay logic uses special hexagonal grid, while various types of tiles (rendered in trimetric projection, which corresponds with point-top hexagons stretched in 2:1 (X:Y) ratio) have different shapes.

    Example:



    We decided to use Tilemaps for all static tiles and preferably static/stationary props, as from the technical standpoint, it seemed to be the most performant solution for our case (large amount of sprites with layers and sorting concerns). We figured out the correct setup for the Grid Layout and our tile sprites. We've also created custom mapping/tile placement tools to substitute missing features within native Tilemap tools. However, there's one huge technical obsticle we haven't been able to overcome.

    Due to the design requirements, we need a certain level of environmental context implemented. For example, hovering a cursor over any structure tile (walls, doorways, etc.) or prop would result in a simple text description of the object. Additionally, dynamic/animated tiles also require interactibility with cursor (opening/closing doors, etc. - essentially a need to trigger such behavior with a mouse click). For that purpose, we intended to implement custom data structures and functionality into derived Tile classes.

    The problem we subsequently discovered is that there seems to be no way to retrieve individual Tile data from the tilemap. Common way to get Tile object instances rendered in the tilemap is to use the grid coordinates and call a GetTile function on a Tilemap component. Of course, that is only applicable for tilemaps and grids that use tiles with the same shape as the grid (i.e. hex grid = hex-shaped tiles, etc.).

    We tried to use physics to raycast and retrieve Tile objects based on the sprite-shaped collision, although Unity does not provide any way to access individual Tile colliders with neither Collider component. Tilemap Collider component apparently batches all subcolliders into one collision mesh, so the result of raycasting is always th entire collider.

    Basically, what we need is to be able to interact with Tiles based of their sprite shape, not the grid shape or position.

    The only possible solution we see is to switch to using regular Sprite renderers for all objects that require any sort of interactivity, although we are concerned about the performance impact of such setup, as well as possible workflow overheads in the future.

    Is there any way to get around this without having to resort to use Sprite renderers at all? Any hacky way would do in this case.

    Alternatively, does Unity plan on enhancing their Tilemap codebase to support such features, or at least exposing more of the native code for us to code them ourselves?
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,752
    If I understand you, the Unity Tilemap is providing the diamond-shaped visual squares, whereas underneath all that your game logic is operating on the stretched hexagons. Is that correct?

    I think all you need is a utility function that can take any arbitrary world position and give you the hex tile associated with it. That shouldn't even involve the tilemap, except to find its origin, eg, what is considered (0,0)

    What you click and what you decide can always be completely unrelated to the actual presentation objects used.

    Here are some more random notes on hex maps:

    https://www.redblobgames.com/grids/hexagons/

    https://catlikecoding.com/unity/tutorials/hex-map/
     
  3. Lo-renzo

    Lo-renzo

    Joined:
    Apr 8, 2018
    Posts:
    1,514
    Hacky untested idea: use tilemap, but shuffle around several pooled SpriteRenderers with colliders in the area of the cursor to replicate what's on the tilemap but with more precise physics.

    tilemap.GetSprite(cell), apply that sprite in the cell's position to the SpriteRenderer, position its transform, repeat for all cells in area of cursor, then raycast to get the exact one. Maybe this requires slight delay before raycast or to manually force physics update; I forget how that works.

    This would also allow you to apply a special material/outline just to the highlighted sprite.
     
    Last edited: Mar 20, 2022
  4. AdamLacko

    AdamLacko

    Joined:
    Oct 10, 2017
    Posts:
    41
    No, not at all. The gameplay logic (character movement, distance calculations, etc.) is performed on the same hexagonal grid that is used for tile placement - the one you can see in the example pictures above - point-top hexagon stretched in 2:1 ratio (Y size is a half of X coordinate). All that is achievable and working within Unity. I only emphasized the grid description to better explain that the sprites we are placing (a ground tile on the first example, a wall tile in the second example) on the grid are not of the grid cell shape nor size (unlike in top-down games with, say, square grid where tiles are also squares and they fit within the grid cell - which is apparently the intended usage of the entire Tilemap system it seems). The placement and the logic is working fine, the only problem is that there is no way to get a Tile object based on mouse position with this setup. In the usual case - where tiles are of the shape and size of the grid (say, square or isometric square tiles on square or isometric square grid respectively) - you could simply get the mouse position and convert it do grid coordinates with already provided functions. In our case, however, this is not a way.
     
  5. AdamLacko

    AdamLacko

    Joined:
    Oct 10, 2017
    Posts:
    41
    I admit this could be a solution, however I am concerned about an unreasonably high CPU overhead caused by complex calculations and object handling in runtime.
     
  6. Lo-renzo

    Lo-renzo

    Joined:
    Apr 8, 2018
    Posts:
    1,514
    The idea doesn't sound nonperformant to me since it only needs to refresh when the mouse cell changes, which is infrequent. The idea, however, sounds perhaps complex, but relative to what alternative?
     
  7. AdamLacko

    AdamLacko

    Joined:
    Oct 10, 2017
    Posts:
    41
    Well, maybe the displayed cursor in the screenshots above indicated that the in-game selection is constrained to the grid. Hexagonal cursor is in fact just one cursor type used for character movement. Interactions would happen with a regular mouse pointer, which changes position very frequently.