How to add animated tiles to a TileMap?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By CelestialCreator

I’ve been using Godot on and off for a bit (v3.2.1.stable.official), and I was playing around with creating TileMaps where some of the tiles are animated. Let’s say I have this 64x64 texture with 16x16 tiles:

64x64 texture with 16x16 tiles

All of the tiles are static, except for the bottom four water tiles that are meant to be used as the frames for one animated tile.

What’s the best way to do this in Godot? Here’s what I’ve tried:

  1. Create four AtlasTexture resources, one for each frame, using the 64x64 texture as the atlas and using the region field to specify the location of the frame. Then, I created an AnimatedTexture resource and assigned these four AtlasTextures as its frames. I then added this AnimatedTexure to the TileSet. While I can place the tile in the TileMap now, it doesn’t animate - in fact, in only shows the “four-leaf clover” tile in the top-left corner of the original 64x64 texture. Out of curiosity, I also tried assigning this AnimatedTexture to a Sprite node, and got the same behavior: no animation and it only renders the four-leaf clover.

  2. I then tried to export each frame as its own 16x16 png and import them into Godot as separate textures. I created another AnimatedTexture and assigned each of these four textures as its frames. Then, I added this AnimatedTexture to the TileSet like before. This works - I can place the tile in the TileMap and it animated as expected. However, it feels inefficient. Instead of one 64x64 texture containing everything, I now have five textures. I can’t help but feel there’s a better way to do this.

  3. I also tried playing around with the AnimatedSprite node, even though it can’t be placed in a TileMap. It takes in a SpritesFrame resource and upon creating that resource, I noticed that it had a button to add frames from a sprite sheet:
    add frames from a spritesheet button I was then able to select the original 64x64 texture, select the four water frames, and voila! The AnimatedSprite animates the water! So it looks like it is possible to animate specific regions of a texture. However, the plot thickens: I opened up the scene in a text editor, and the AnimatedSprite is made using AtlasTexture sub-resources referencing the original 64x64 texture! Which is precisely what I was trying to do in my first attempt (just with an AnimatedTexture resource instead). I tried to save the SpriteFrames resource as an external resource and add it to the TileSet resource, but it doesn’t appear that this is supported.

Based on this and the research I’ve done so far, it sounds like there’s two options:

  • Import each frame of animated tiles as their own textures
  • Manually position AnimatedSprites instead of using the TileMap

I’m not really satisfied with these solutions though, since the first one leads to tons of additional textures, and the second doesn’t utilize the TileMap. So, back to my original question: What’s the best way to animate a tile in a TileMap where its frames are contained in the same texture as other static tiles? Is it possible to use one texture for everything, or is there no other option than to export each frame as its own texture?

I appreciate any thoughts or insights on this!

:bust_in_silhouette: Reply From: rakkarage
shader_type canvas_item;
render_mode unshaded;

uniform sampler2D frames: hint_albedo;
uniform float count;
uniform float duration;
uniform float width;
uniform float startX = 0;

void fragment() {
	float frame = floor(mod(TIME, count * duration) / duration);
	float offset = floor((UV.x - startX) / width);
	COLOR = texture(frames, UV + vec2((mod(offset + frame, count) - offset) * width, 0));
}

when you create an atlas in the tileSet you can set a single material and shader for whole atlas that will get a different UV for for each tile in the animation you can use this to animate each from a different point so you can select priority in editor to paint random frame start animations or uncheck priority to paint synced animations

can use single shader for all tilemap animations just make a new material if need different settings ((except blend mode) no setting for that for some reason need new shader)

i am sure it could be improved a bit but seems to work well