Search Unity

Feedback [Tilemap] ITilemap is a pain

Discussion in '2D' started by Baste, Dec 3, 2020.

  1. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,338
    I need to figure out why a RuleOverrideTile isn't producing a tile at a certain location. In order to do that, I want to call the tile's GetTileData with the correct tilemap and location, attach a debugger, and see what it does.

    Except GetTileData doesn't take a Tilemap, it takes an ITilemap. And what on earth is ITilemap good for?

    Here's a list of all the things ITilemap does:
    - wraps a Tilemap
    - has a static instance

    In other words, it's useless. At the same time, the m_Tilemap member, and all the methods that set them, are internal, so we can't use them in our code! And pretty much all the code that should work on a Tilemap instance instead works on an ITilemap instance, so we don't get to call any of it, since we can't make ITilemaps.


    I mean it shouldn't even be called ITilemap, it's not a damn interface. If it was an interface, then we could've implemented it and it'd maybe been useful, but it's not.

    Gah!

    So my feedback is:
    - please let us either create ITilemap instances ourselves, so it's possible to call any of the methods in TIleBase. Here's the code, you can copy-paste it to your codebase for free:
    Code (csharp):
    1. public ITilemap(Tilemap tilemap) => this.m_Tilemap = tilemap;
    One line of code, and now your API is suddenly useful!

    - or even better, kill the ITilemap, it's horrid. If you're really afraid of code modifying the tilemap and want to pass around a "readonly" version of the tilemap, create an interface named IReadOnlyTilemap that's only an interface. That way I wouldn't have read through the source on GitHub or a decompiler to understand what the hell you're doing.
     
    GamerXP, oakus and Lo-renzo like this.
  2. GamerXP

    GamerXP

    Joined:
    Mar 22, 2014
    Posts:
    78
    I was trying to use call some of RuleTile's methods from Tilemap.tilemapTileChanged event, to create do some extra tiles manually (with checking if they should be created with that RuleTIle). But RuleTile's methods accept only ITilemap.
    That ITilemap should be an actual interface, and Tilemap should implement it. Or give us a method to get ITilemap from it somehow.

    Well, I've solved it for now in a hacky way:

    Created such a script
    Code (CSharp):
    1. namespace UnityEngine.Tilemaps
    2. {
    3.     public static class ITilemapUtility
    4.     {
    5.         public static ITilemap GetITilemap(this Tilemap _tilemap)
    6.         {
    7.             var inst = ITilemap.s_Instance;
    8.             inst.SetTilemapInstance(_tilemap);
    9.             return inst;
    10.         }
    11.     }
    12. }
    And put it into a magical Assembly with name "Assembly-CSharp-Editor-testable" - scripts in this assembly get access to all internal APIs. Yay for magical assemblies! Maybe we can have a flag "Access internal API" in Assembly Definition at some point? I can't count how many times all this internal API thingy got in my way at this point.

    PS. Also, why at it, can Tilemap.tilemapTileChanged give some more info? Like, what TileBase was in the cell before it was removed - you only get TileData which does not provide info about the source.