Tilemap.Boxfill() working like Tilemap.FloodFill() ?

Hello,

I’m doing a simple game with tilemaps where you are given a 8x8 filled grid and you create a “path” through the grid by deleting some of the tiles with a mouse click. I create this grid with a script using Tilemap.Boxfill() and it works just fine.

I also wanted to add a “reset” button so that the grid would be restored to it’s original state and to do so I wanted to use the same Tilemap.Boxfill() command, however, whenever I click it, it seems to do a Flood fill from the origin instead of a Boxfill centered on the origin.

The code I’m using to both spawn the 8x8 tilemap and to reset it are as follows:

[SerializeField] Tilemap tilemap;

void Start()
    {
        tilemap.BoxFill(Vector3Int.zero,tiles[0],-4,-4,4,4);
    }

public void redoTilemap(){
   
        tilemap.BoxFill(Vector3Int.zero,tiles[0],-4,-4,4,4);
   
    }

with the last function used when the reset button is clicked.

Below I also have a little example of what I mean:

8491871--1129832--upload_2022-10-5_13-56-29.png
the grid after deleting some tiles, center marked with the blue X

When clicking reset, it runs the “redoTilemap()” function mentioned above.
8491871--1129844--upload_2022-10-5_13-58-21.png
The resulting “Boxfill”: A floodfill around the center

The result is that I get a floodfill isntead of a Boxfill.
One way around it would be clean all of the tiles of this tilemap, change it’s boundaries and then do a box fill. But it was my understanding that just running the given BoxFill would do the trick.

8491871--1129835--upload_2022-10-5_13-57-53.png
8491871--1129844--upload_2022-10-5_13-58-21.png
8491871--1129844--upload_2022-10-5_13-58-21.png

I’m guessing that’s not quite what is happening.

I noticed coordinates from -4 to +4, but I notice a first argument of tiles[0]

This seems at least suspiciously inconsistent.

I’m guessing the boxfill would work if you started it from (0,0) and used (width,height), which is a more traditional numbering system, zero-based, rather than going negative from some initial offset.

at first glance, this should work. Tiles[0] is just a tile, and the values for the limits look correct.

Try using SetTiles or SetTilesBlock instead.

It’s impossible to tell what’s going on under the hood (for us mere mortals) since this method goes directly into the engine.

You could try a bug report with an example.

Can those coordinates really be negative for a Tilemap?

I have only barely coded against the Tilemap interface but everything I did was in 0 to width-1 and 0 to height-1, but I was only using the SetTile() method. I just ASSUME this BoxFill would be based on top of the same zero-based coordinate system…

At the end of the day I know that a simple nested pair of for() loops with zero to max-1 for each axis will JustWork™ and is likely to be nearly as performant as BoxFill, which probably just does that itself anyway.

Seems to be a bug indeed, I am using an older version 2020.3.11f1 since I was doing a previous project on that one and didn’t bother to update it, so maybe it’s already fixed.

I did another test, putting some tiles around the starting position of the grid before running the scene and it truly works as a “bounded floodfill” of sorts.

8491979--1129865--upload_2022-10-5_14-44-9.png
blue x on the origin. This in the scene, before running the game.
8491979--1129868--upload_2022-10-5_14-45-3.png
Its a flood fill!

Heres hoping that it’s something that’s already been fixed in further version.

Since we’re already on this thread. ClearAllTiles resets the tilemap to it’s default values, on this case, both the center and the extents go to (0,0,0). Is there a way to change the extents back to whatever it is I want them to be or do I have to set a customized default myself somewhere?

For sure you can have negative coordinates for tiles.

One does have to be careful with the math, esp if you use Tilemap.cellbounds.AllPositionsWithin enumerator to index into an array of tiles from GetTilesBlock retrieved using that same Tilemap.cellbounds (this bit me!).

Like a number of other methods in Unity, this one may not work as you expect. You could be correct that it only works properly for positive values (and it may have been reported previously as a bug).

It may be that they create a bounds or boundsint internally and negative values make the boxfill algo go nuts.Note that the standard Unity palette brush has a BoxFill method but even that doesn’t use Tilemap.Boxfill to actually execute the operation.

But there’s always a workaround :slight_smile:

re: Since we’re already on this thread. ClearAllTiles resets the tilemap to it’s default values, on this case, both the center and the extents go to (0,0,0). Is there a way to change the extents back to whatever it is I want them to be or do I have to set a customized default myself somewhere?

Not sure, but try: ResizeBounds . But I’m not sure why you’d want to mess with this; adding tiles to an empty tilemap will resize the bounds automatically.

Good luck!

Thats the thing, when I used clearAllTiles() it set everything to zero, but using boxFill would not resize it, and so the size of the tilemap was not adjusted and instead both were moved to (0.5,0.5,0.5) adding a single tile (???) . To get everything to work properly now I manually reset the size and center of the tilemap to the way it was previously.

public void redoTilemap(){
      
       tilemap.ClearAllTiles();
     
       tilemap.size = new Vector3Int(23,10,1);
       tilemap.origin = new Vector3Int(-10,-4,0);
        tilemap.BoxFill(Vector3Int.zero,tiles[0],-4,-4,4,4);

    }

Now, why is the origin on (-10,-4,0) and the size on (23,10,1) I myself have no clue as I didn’t do anything with both, but that’s what the debug inspector showed and that’s what makes it work properly.

Unfortunately, this API was not worded properly. Tilemap.BoxFill works like Tilemap.FloodFill, except bounded within the given range. Using Tilemap.SetTiles or Tilemap.SetTilesBlock will give you what you expect.

The origin and size of the Tilemap defines the limits of your Tilemap, so for your given range, these would be the values:

public void redoTilemap()
{    
       tilemap.ClearAllTiles();
       tilemap.origin = new Vector3Int(-4,-4,0);       
       tilemap.size = new Vector3Int(9,9,1);
       tilemap.BoxFill(Vector3Int.zero,tiles[0],-4,-4,4,4);
}
1 Like