I am using Godot autotiles to create levels, and I would like to be able to place grass on top of other grass (like how Minecraft has a grass block, and then on top of the grass there are things like flowers and grass). I already have a full terrain set as well as well as the grass, and grass variants(such as flowers), I just need to know how to implement ruleset of "if outside facing grass tile, add additional grass plant on top." I am also planning to use whatever method is given to me to also add leaves to trees, or rock debris on top of stone, I am just using grass as the example. If possible having multiple layers for this would also be nice but I don't know if that's possible or not.

I have tried manually placing the additional grass, however this solution takes far to long to preform for even a single level, as the grass is multi directional(slopes have their own grass sprite, side facing stuff has its own grass etc etc).

Patterns seem promising however I can't find any documentation on how to use them in an autotile(maybe I'm missing something here?)

I have also looked into a few autotile/terrain plugins but none of them seem to document this kind of behavior.

I have also looked into coding my own plugin or procedural autotile ruleset by extending the built in tilemap node. However, as I am working on a game jam, I don't want to waste an extraordinary amount of time doing that if there is already a built in way to do this.

1

There are 1 answers

0
Theraot On BEST ANSWER

The TileMap system had a lot of changes in Godot 4, and the documentation has not cached up.

Yes, you can do layers in the TileMap in the Inspector. But you can't make rules for autotiling that span multiple layers. And no, patterns do not do autotiling.


It is possible to have randomness in autotiling. This might be sufficient for your goals. It is something like this:

  • You can define multiple terrains in the TileSet in the Inspector. Each terrain has a color, that is just an aid to identify them.
  • Then you can paint the terrain on top of the tiles. To do that go to the TileSet panel (at the bottom, do not confuse it with the TileMap panel), select the Paint tab, and then choose Terrain (if you had it selected while you changed the terrains, you want to selecto something else and select it again to force an update). And then you can paint the edges corners and center of each tile with a different terrain. This is what Godot will use for autotiling.
  • Then you can go to the TileMap panel to draw in your TileMap. Select the Terrains tab, pick a terrain and paint it. Now, since Godot is using the way you painted those terrains on the TileSet, there might be multiple valid tiles for a given position (e.g. you painted multiple tiles the same way). In that case Godot will pick at random.
  • For that randomness Godot is using the probability property. Which you can set in the TileSet panel, again in the Pain tab, but this time select Probability instead of Terrain... Probability happens to be a misnomer, it is a weight (the higher the value the more likely, and the lower the value the less likely, but they do not have to add up to 1).

With that you can have autotiles that have random tiles when you paint them. So you can have a grass tile, and a grass tile with flowers and have Godot pick randomly.


Now, if you need to do this with multiple layers, then try using the scatter tool instead.

In the TileMap panel, in the Tiles tab there will be a tool that looks like a dice with the tooltip "Place Random Tile", this will place tiles from your selection at random (including the chance of no tile, controlled by the scattering value that appears when the tool is selected).

You can use this to - for example - have grass on the first layer, and then draw flowers randomly on a second layer.


I suppose you could make a script that iterates over one of the layers of your TileMap and populates a second layer at random.

Use get_used_rect to get the area over which you need to iterate.

To read the terrain of a tile you need to use get_cell_tile_data, which gives you a TileData object that has a terrain property.

And the set_cell method can take the layer, the position, and the id of what you want to place.

You can then come up with your rules for what tile id to place on the second layer depending on the terrain of the first layer.