Skip to content

Godot 4.x

How to import a sprite sheet into Godot 4

Godot 4 can slice a uniform sprite sheet straight from the SpriteFrames editor. This guide uses the ZIP export, which gives you a grid-aligned PNG plus a JSON file with named animations.

1. Download the ZIP

  1. Open your sprite (from Drive or the public gallery) and choose ZIP under Download Assets.
  2. Unzip it. You need normalized_spritesheet.png, the frames/ folder and spritesheet.json.
  3. Open README.txt: it lists the cell size (for example 128 x 128) and the grid (for example 4 columns x 4 rows). You'll type these numbers into the engine.

Pro Motion sheets store the exact playback rate in spritesheet.json (animations → fps). For other sheets the defaults are listed below.

2. Add the sheet to your project

  1. Copy normalized_spritesheet.png (and spritesheet.json if you want the script below) into your project, for example res://sprites/knight/.
  2. For pixel art, set Project Settings → Rendering → Textures → Canvas Textures → Default Texture Filter to Nearest, or set Texture → Filter to Nearest on the node, so pixels stay crisp.

3. Slice it with AnimatedSprite2D

  1. Add an AnimatedSprite2D node. In the Inspector, set Sprite Frames → New SpriteFrames, then click it to open the SpriteFrames panel.
  2. Click Add Frames from Sprite Sheet (the grid icon) and pick normalized_spritesheet.png.
  3. Set Horizontal to the number of columns and Vertical to the number of rows from README.txt. The preview snaps to the cells.
  4. Select the cells for one animation (for a 4-direction walk cycle, row 1 is walk_down, row 2 walk_left, row 3 walk_right, row 4 walk_up) and click Add Frame(s).
  5. Rename the animation to match, set its speed (FPS) and turn on looping. Repeat for each row.

Every frame is centered inside its cell, so a center pivot keeps the animation steady. If you want the pivot at the character's feet, set it once to the same point for every frame; because all cells are the same size, one value works for the whole sheet. AnimatedSprite2D is centered by default; use Offset to move the pivot.

Alternative: Sprite2D with hframes and vframes

  1. Add a Sprite2D, set Texture to the sheet, then set Animation → Hframes to the column count and Vframes to the row count.
  2. Animate the Frame property with an AnimationPlayer. Frame 0 is the top-left cell and numbering continues left to right, row by row.

Optional: build SpriteFrames from spritesheet.json

Walk cycles, action sets, enemy variants, VFX and creative sheets include an animations map. This script turns it into a SpriteFrames resource with the right names, FPS and looping.

sprite_sheet_loader.gd (Godot 4)
func build_sprite_frames(json_path: String, sheet: Texture2D) -> SpriteFrames:
	var data: Dictionary = JSON.parse_string(FileAccess.get_file_as_string(json_path))
	var frames := SpriteFrames.new()
	frames.remove_animation("default")
	for anim_name in data.get("animations", {}):
		var anim: Dictionary = data["animations"][anim_name]
		frames.add_animation(anim_name)
		frames.set_animation_speed(anim_name, anim["fps"])
		frames.set_animation_loop(anim_name, anim["loop"])
		for frame_name in anim["frames"]:
			var rect: Dictionary = data["frames"][frame_name]["frame"]
			var atlas := AtlasTexture.new()
			atlas.atlas = sheet
			atlas.region = Rect2(rect["x"], rect["y"], rect["w"], rect["h"])
			frames.add_frame(anim_name, atlas)
	return frames

JSON files aren't imported as resources. When you export the game, add *.json to the export preset's non-resource file filter, or convert the result to a .tres SpriteFrames in the editor.

Reference: what's in the ZIP

normalized_spritesheet.png
The sheet on a uniform grid: every cell is the same size, frames read left to right, top to bottom, on a transparent background.
frames/frame_001.png …
One PNG per frame, numbered from 001 in playback order, each the size of one cell.
spritesheet.json
Engine-friendly metadata: meta.size, a frames map with the x, y, w, h rectangle and duration (ms) of every frame, and for animated modes an animations map with frame names, fps and loop.
metadata.json and README.txt
Cell width and height, the grid (columns × rows), frame count and the original prompt.
original.png
The source image before the frames were normalized onto the grid.

Default playback rates

Sheet typeFPS
4-direction walk cycles8
Character action sets10
Enemy idle animations6
VFX effects12
Creative animations8

Frequently asked questions

Which Godot node should I use for an AI-generated sprite sheet?

Use AnimatedSprite2D when you want named animations (walk_down, attack and so on) edited in the SpriteFrames panel. Use Sprite2D with hframes and vframes when you drive the frame index yourself from an AnimationPlayer or code.

What FPS should I use in Godot?

Use the fps value in spritesheet.json. The defaults are 8 FPS for 4-direction walk cycles, 10 FPS for character action sets, 6 FPS for enemy idle animations, 12 FPS for vfx effects, 8 FPS for creative animations.

Why do my pixel-art sprites look blurry in Godot?

The default canvas texture filter is Linear. Switch it to Nearest in Project Settings (Rendering → Textures → Canvas Textures) or on the node's Texture → Filter property.