How to import a sprite sheet into Godot 4
Godot can slice a sprite sheet itself, so importing one is usually four clicks. The part that costs people an afternoon is everything around it: the art comes out blurry, the slicer refuses a packed atlas, or the sprite shimmers as the camera moves. All three have specific causes.
Do this before anything else: turn off the blur
Godot 4 filters 2D textures linearly by default. On a photograph that is correct. On a 32×32 sprite scaled up 4× it means every pixel is smeared into its neighbours, and the result looks like a JPEG someone rescued from 2004. This is the single most common Godot pixel art complaint, and it is one setting.
Project → Project Settings → Rendering → Textures → Canvas Textures → Default Texture Filter, and set it to Nearest. It applies to the whole project, which is what you want — a per-node fix that you have to remember on every new sprite is not a fix.
For a mixed project — pixel art characters over a smooth-shaded background — leave the default as Linear and override it per node instead. Every CanvasItem has Texture → Filter in the inspector, and setting it on a parent node is inherited by its children, so one override on the container that holds your sprites covers all of them.
Note that this changed between versions. In Godot 3 filtering was an import flag on the texture, which is why older tutorials tell you to uncheck "Filter" in the Import dock. In Godot 4 that flag is gone — filtering is a property of the thing drawing the texture, not the texture.
1. Put the file in the project
Copy the PNG anywhere under the project folder. Godot notices it the next time the editor window has focus, imports it, and writes a small yoursheet.png.import file beside it. That .import file belongs in version control; the .godot/ folder it points into does not.
Re-exporting the sheet from your art tool over the top just works — Godot re-imports and everything referencing it updates. If it ever appears stuck on an old version, deleting .godot/imported/ and reopening the project forces a clean re-import.
2. Pick the node that matches what you have
Three nodes read sprite sheets, and choosing the wrong one is why some people end up animating by hand.
AnimatedSprite2D
Character animations — idle, walk, attack
Holds a SpriteFrames resource containing named animations, each with its own frame list and FPS. This is the one you almost always want. It can slice a sheet for you.
Sprite2D + Hframes/Vframes
A uniform grid you drive yourself
Set Hframes and Vframes to the grid size and the Frame property picks a cell. Useful when an AnimationPlayer already controls the object and you just want to key frame alongside position and rotation.
TileSet on a TileMapLayer
A tileset, not an animation
A sheet of terrain tiles is a different problem with a different editor. Create a TileSet, add the sheet as an atlas source, and set the tile size there.
3. Slice the sheet with AnimatedSprite2D
Add an AnimatedSprite2D. In the inspector, click Sprite Frames → New SpriteFrames, then click the resource to open the SpriteFrames panel at the bottom of the editor.
In that panel, the second toolbar button is Add frames from a sprite sheet (the first one adds individual image files). Pick your PNG and a dialog opens with the sheet and a grid over it:
Horizontal / Vertical — how many columns and rows, not the pixel size of a cell. An 8×4 sheet of 32px frames is 8 and 4.
Separation — the gap between cells, if the exporter left one.
Offset — a margin around the outside of the grid.
Then click the frames you want, in order. This is the step people miss: the dialog does not select everything by default, and the order you click is the order the frames play. Drag across a row to take it in one go. Rename the animation from default to something real, set the FPS, and turn the loop toggle on or off.
One sheet usually holds several animations. Add the animations first, then run the dialog once per animation, selecting only that row each time — a single default animation containing every frame on the sheet is not something you can use later.
If you are not sure the frame order or rate is right before committing to it, the Sprite Animation Previewer plays the sheet back at any FPS in the browser, which is faster than round-tripping through the editor.
4. When Godot's slicer cannot do it
The built-in slicer models a sheet as an even grid with a fixed separation. That covers most hand-made sheets and everything Aseprite exports as a strip. It does not cover:
A packed atlas. Frames of different sizes, packed to save space, with no consistent grid — the output of TexturePacker or any "pack sprites" option. Godot has no importer for the JSON or .plist that describes such an atlas; you would be creating an AtlasTexture resource per frame by hand, entering each region rect manually.
Unless something writes those resources for you. The Sprite Sheet Generator exports a SpriteFrames resource alongside the sheet — pick Godot 4 (SpriteFrames) as the manifest format and you get a .tres holding one AtlasTexture per frame, region rects filled in, with the trim offsets written as each texture's margin so a trimmed frame still occupies its original footprint. Put the .tres beside the PNG at the project root, drop it onto an AnimatedSprite2D, and it plays. That handles the packed case and the trimmed case at once; the frame rate is written as 10 and is a field in the inspector afterwards.
A grid with inconsistent spacing, which happens when a sheet was assembled by hand or cropped after export.
Frames that need trimming or reordering before they are useful.
In all three cases, cut the sheet outside Godot into individual PNGs and drag those into SpriteFrames instead — that path has no grid requirement at all. The Sprite Sheet Cutter does it by grid or by automatic detection, which finds islands of non-transparent pixels and works on a packed atlas, and gives you a ZIP of numbered frames. Godot sorts dragged-in files naturally, so run_2.png lands before run_10.png.
5. The import options worth changing
Select the PNG in the FileSystem dock and switch to the Import tab. Defaults are sensible for 2D, but two are worth a look for pixel art:
Compress → Mode should stay Lossless. VRAM Compressed is block compression — it saves memory on large textures and mangles small sprites with hard colour boundaries, which is exactly what pixel art is.
Mipmaps → Generate should stay off for 2D. Mipmaps are pre-blurred smaller copies used when a texture is drawn below its native size; switching them on for a sprite sheet is a way to get blur back after you just turned it off.
Process → Fix Alpha Border should stay on. It fills the colour channels of fully transparent pixels with the nearest opaque colour, so filtering near a sprite's edge cannot pull in black and leave a dark halo. Harmless with Nearest filtering, and it saves you when something downstream does filter.
Change anything and press Reimport — the tab does not auto-apply.
6. Make the whole game scale by whole numbers
Nearest filtering stops the texture being blurred. It does not stop a fractional scale, and that produces the other classic artefact: some pixels two screen pixels wide and their neighbours three, so the sprite shimmers and wobbles as it moves.
Under Display → Window → Stretch, set Mode to canvas_items and Scale Mode to integer. Godot then only ever scales the viewport by a whole number and letterboxes the remainder, rather than scaling by 2.4 and leaving you to explain the shimmer.
Two more things break this after the fact. A Camera2D with a zoom like 2.5, and a node scale that is not a whole number — including one produced by a tween easing between two values. If a sprite shimmers only while it is animating, check the tween.
Related: decide your art's native resolution once and author at it, rather than pre-scaling sprites to 4× before import. Bigger textures for no extra detail, and Godot scales for you anyway. If you have inherited art that was already upscaled, the Pixel Art Resizer can detect the factor and take it back to native.
Common problems
Pixel art looks blurry in the running game
Default Texture Filter is still Linear. Project Settings → Rendering → Textures → Canvas Textures. In Godot 4 this is not an import setting, whatever a Godot 3 tutorial says.
It looks sharp in the editor and blurry when running
The stretch mode is scaling the viewport up with filtering. Set Scale Mode to integer under Display → Window → Stretch.
Thin lines of the next frame appear along a sprite's edge
The declared grid does not match the sheet — usually undeclared separation between cells. Every column drifts a little further off, so check the last column, not the first.
The animation plays in the wrong order
The slice dialog records the order you clicked the frames in, not their position on the sheet. Clear the animation and re-select left to right.
Only one animation exists and it contains everything
The dialog was run once over the whole sheet. Add an animation per action first, then slice once per animation with only that row selected.
A dark outline around sprites over a light background
Transparent pixels carry black in their colour channels and something is filtering across the edge. Turn on Fix Alpha Border in the Import tab and reimport.
Godot will not slice the sheet evenly at any setting
It is a packed atlas, not a grid. Cut it into individual PNGs outside the editor and drag those in.
Tools used here
Sprite Sheet Cutter
LiveSplit a sprite sheet into individual PNG frames by grid, auto-detection or an Aseprite JSON, then download them as a ZIP.
Sprite Animation Previewer
LivePlay a sprite sheet at any FPS — or with Aseprite's own per-frame timing and tags — and export a GIF.
Pixel Art Resizer
LiveScale pixel art 2x / 4x / custom with nearest-neighbour — no blurring.