A Godot 4 blob autotile is
47 tiles, not 256.

Eight neighbours, two states each, is 256 neighbourhoods — and a terrain in corners and sides mode needs exactly 47 tiles to cover all of them. The rule that collapses one number into the other is that a corner peering bit only counts when both of its adjacent side bits are set. Below you can click a neighbourhood and see which tile Godot picks for it, and paste your TileSet resource to find out which of the 47 your set is missing. Every claim on this page was measured by running Godot 4.7 — including what the engine does with a tile you did not draw, which is not what most people assume.

1 · Click the neighbours, get the tile

Filled = a cell of the same terrain is there. The centre is the cell being resolved.

NEIGHBOURHOOD0
TILE THE ENGINE PICKS0
TILE INDEX (of 47)0
NEIGHBOURHOODS SHARING IT1

The lines this tile needs in your .tres, written by the same generator Blobsmith ships (atlas coordinates are for the standard 8-column sheet):


  

2 · Paste your TileSet and find the holes

Nothing is uploaded — the check runs in this page. It reads terrain_set_0/mode and every terrains_peering_bit/* line, and compares the neighbourhoods your tiles claim against the 47 the engine distinguishes.

    Where 47 comes from

    Godot's terrain system, in TERRAIN_MODE_MATCH_CORNERS_AND_SIDES, matches a cell against its eight neighbours: four sides (top, right, bottom, left) and four corners (the diagonals). Naively that is 28 = 256 distinct neighbourhoods and 256 tiles to draw. Nobody draws 256, and nobody needs to:

    A diagonal neighbour is only visible when both sides next to it are also filled. If the cell to your north-east is filled but the cells to your north and east are not, that diagonal touches your tile at a single point — there is nothing to draw differently, so Godot does not distinguish the case. The corner bit is only meaningful in the presence of both adjacent side bits.

    canonical(mask):
      keep the four side bits
      keep NE only if N and E are also set
      keep SE only if S and E are also set
      keep SW only if S and W are also set
      keep NW only if N and W are also set

    Run all 256 neighbourhoods through that and the distinct results number exactly 47. They are not evenly loaded: 16 of the 47 tiles serve a single neighbourhood each, 16 serve 4 each, 8 serve 8 each, and 7 serve 16 each — 16 + 64 + 64 + 112 = 256. The all-neighbours tile (mask 255) is one of the seven that answer sixteen different neighbourhoods; the island tile (mask 0) answers sixteen as well, because with no sides filled all four diagonals are decoration.

    The same arithmetic in the other mode: TERRAIN_MODE_MATCH_SIDES ignores diagonals entirely, so it is 24 = 16 tiles, no collapsing needed. Corners-only mode is 16 as well. If you are counting 47, you are in corners-and-sides.

    We asked the engine all 256 times

    The rule above is a claim about what Godot does, so it is answered by Godot and not by us. A script loads a complete 47-tile TileSet, and for each of the 256 neighbourhoods it paints the centre cell plus exactly those neighbours with set_cells_terrain_connect(), then reads the peering bits back off the tile the engine chose for the centre:

    tools/godot-test/verify_blob47.gd   (Godot 4.7.stable, headless)
    
    PASS  all 256 neighbourhoods painted a tile
    PASS  engine agrees with the corner-needs-both-sides rule on all 256
    PASS  engine distinguishes exactly 47 tiles (got 47)
    PASS  a lone NE corner is not distinguished from no neighbour at all
    PASS  N+E without the NE corner differs from N+E+NE

    256 out of 256 agreements, and the 256 answers land on 47 distinct tiles. The script prints the whole table as JSON, so the tool at the top of this page is judged against the engine's answers rather than against our prose — if a future Godot changes the rule, the table stops matching and the page is wrong out loud.

    What Godot does with a tile you did not draw

    This is the part that sends people searching. A blob sheet with a hole in it does not produce an error, a warning, or an empty cell. The engine picks the closest tile it has and paints it.

    Measured: take the complete set, delete the all-neighbours tile at runtime, and repaint a solid 3×3 block whose centre needs exactly that tile.

    tools/godot-test/verify_blob47_holes.gd   (Godot 4.7.stable, headless)
    
    control  centre = N+NE+E+SE+S+SW+W+NW   atlas (6, 5)
    hole     centre = N+NE+E+S+SW+W+NW      atlas (4, 5)   source_id 0
    
    PASS  with the hole, the centre is NOT left empty
    PASS  with the hole, the centre is a DIFFERENT tile than the correct one
    PASS  the substitute is missing at least one peering bit the neighbourhood has

    The interior cell was silently given a tile that claims no bottom-right corner. On screen that is one cell with an edge or a notch drawn through the middle of a solid area — the classic "my autotile has a seam in it and I cannot find why". Nothing is printed to the output panel. That is what the checker above is for: it lists the neighbourhoods your set cannot answer before you go hunting for the seam.

    The two coordinates in that log are also a cross-check on the tool at the top: the engine picked atlas (6, 5) for the all-neighbours tile, which is where tile index 46 lands on an 8-column sheet — the position the generator on this page computes for mask 255 without ever asking the engine.

    How the peering bits are written in the file

    Inside a TileSetAtlasSource, each tile is a block of properties keyed by its atlas coordinates and alternative id. A tile that belongs to a terrain carries three things plus one line per neighbour it matches:

    6:5/0 = 0
    6:5/0/terrain_set = 0
    6:5/0/terrain = 0
    6:5/0/terrains_peering_bit/right_side = 0
    6:5/0/terrains_peering_bit/bottom_right_corner = 0
    6:5/0/terrains_peering_bit/bottom_side = 0
    ...
    [resource]
    terrain_set_0/mode = 0
    terrain_set_0/terrain_0/name = "Grass"

    The value after = on a peering-bit line is the terrain index, not a boolean — = 0 means "this side matches terrain 0", and a bit that is absent means "nothing here". That is why a hand-edited set with the wrong terrain index looks filled in the editor and still paints wrong: the bits are set, just to a terrain that is not the one you are painting.

    What the checker seesWhat it means
    missing tileNone of your tiles claims that canonical neighbourhood. The engine will substitute a wrong tile, silently, in the situation described above.
    duplicateTwo tiles claim the same neighbourhood. Legal, and one of them will never be chosen — usually a copy-paste that was meant to be edited.
    unreachableA tile carries a corner bit whose adjacent side bits are not both set. No neighbourhood in the engine's own table maps to it, so it can never be painted by the terrain system.
    mode mismatch47 tiles with terrain_set_0/mode = 2 (sides only), or 16 tiles in corners-and-sides mode. The mode decides which bits the engine even reads.

    What the checker deliberately does not claim: it reads a text resource, so it cannot tell you whether the art in each cell is correct, whether the atlas region actually contains pixels, or whether your TileMapLayer points at this TileSet at all. It answers one question — is the set complete and consistent for terrain painting — and stays out of the rest.

    If you would rather not draw 47 tiles

    🧱 Blobsmith — 6 tiles in, a wired 47-tile TileSet out

    Draw six tiles in a 2×3 block and it composes the whole 47-tile blob sheet by quadrants, writes the .tres with the terrain set, every peering bit and optional collision already configured, and a Tiled .tsx beside it. Runs in the browser. Free Lite version · Blobsmith on itch.io

    🔩 The free addon

    An editor plugin that wires an existing 47-tile sheet inside Godot, plus the format notes this page is built on. blobsmith-autotile-wirer on GitHub

    🧩 The bytes under a painted layer

    Once the terrain paints correctly, the cells live in one undocumented property. tile_map_data, decoded — with a decoder you can paste into

    🌍 Godot prints the key instead of the translation

    The other silent Godot failure, with the checklist and a CSV linter that runs in the page. Read it