Sprite Sheet Layout: Strips, Grids and Texture Atlases
Strips, grid sheets and packed atlases compared: frame padding, texture bleeding, texture size limits and memory, with settings for Unity, Godot and GameMaker.
By SpriteLab team6 min read
The short answer
Keep your source animations as simple strips or grids of equal-size frames — they are easy to slice, edit and replace — and let the engine pack them into texture atlases for the build. Use equal cells with a shared baseline for animations, add 1–2 pixels of padding (or extrusion) around frames that are filtered or scaled, keep single textures at or below 4096 pixels on a side if you target older phones, and remember that an uncompressed RGBA texture costs width × height × 4 bytes of video memory.
Three layouts and when to use them
A horizontal strip holds one animation in one row. It is the easiest format to reason about: frame width is image width divided by frame count, and every engine can split it. A grid sheet stacks several rows — several animations, or several directions of one animation — on one image. A packed atlas places sprites of different sizes wherever they fit, trimming empty space, and keeps a data file with each sprite's rectangle and offset.
| Layout | Best for | Watch out for |
|---|---|---|
| Strip (1 row) | One animation; editing and swapping | Long strips get very wide |
| Grid (rows × cols) | Directional walks, small animation sets | Everyone must agree on row order |
| Packed atlas | Shipping builds, many sprites, mobile | Needs a data file; trimmed frames need offsets |
Why equal cells matter for animation
When every frame has the same width and height and the character stands on the same row of pixels in each, slicing is mechanical and the pivot stays still. Trimmed frames — each cut to its visible pixels — save memory but give every frame a different size; without stored offsets the character jumps around as the animation plays. Atlas tools handle this by remembering each frame's original position; Unity's automatic slicing does not, which is why animation sheets should be sliced by cell size, not automatically.
Padding, bleeding and extrusion
Texture bleeding is a thin line of a neighbouring frame appearing at the edge of a sprite. It happens when the GPU samples slightly outside a frame's rectangle: with bilinear filtering, with mipmaps, or when sprites are drawn at non-integer positions or scales. Pixel art drawn with nearest filtering at whole-pixel positions rarely bleeds; painted art that is filtered and scaled almost always will without padding.
Padding is empty transparent space between frames, typically 2 pixels (4–8 with mipmaps). Extrusion repeats each frame's edge pixels outward into that space, so even if the sampler strays, it picks up the right colour — important for tiles, which have opaque edges. Atlas packers add both for you; hand-made sheets often have neither.
- Unity Sprite Atlas: Padding 2, 4 or 8; turn off Allow Rotation and Tight Packing if sprites look cut off.
- Godot 4: TileSet atlases have Margins and Separation; for animation sheets, Nearest filtering avoids most bleeding.
- GameMaker: texture groups have a Border setting; increase it if neighbouring sprites bleed in.
Texture size limits and memory
Desktop GPUs accept 8192 or 16384 pixel textures; 4096 is the safe maximum if you support older phones and some web targets. Engines also have their own import caps: Unity's default Max Size is 2048, so a wider sheet is silently scaled down at import, which blurs pixel art and breaks slicing. Raise Max Size to at least the sheet's longest side.
Long strips hit these limits sooner than you expect. An 18-frame animation at 256 pixels per frame is 4608 pixels wide — over 4096 and over Unity's default. Split it into rows, export individual frames and let the engine pack them, or downscale the art if your game uses smaller sprites anyway.
| Texture | Uncompressed RGBA | With mipmaps (+33%) |
|---|---|---|
| 1024 × 1024 | 4 MiB | ≈5.3 MiB |
| 2048 × 2048 | 16 MiB | ≈21.3 MiB |
| 4096 × 4096 | 64 MiB | ≈85.3 MiB |
| 4608 × 256 strip | 4.5 MiB | 2D sprites usually skip mipmaps |
Do textures still need to be powers of two?
For plain 2D sprites, no: modern engines and GPUs handle any size. Powers of two still matter in specific cases — some compressed formats on older mobile hardware require them, mipmapping behaves best with them, and atlas packers often round page sizes up to them anyway. If you let the engine build atlases, you do not need to think about this for individual sheets.
Letting the engine pack the atlas
All three popular engines can build atlases from separate sprites for you, which is usually the best of both worlds: you keep simple source files and the build gets efficient textures.
In Unity, create a Sprite Atlas asset (Assets → Create → 2D → Sprite Atlas), add the folders that hold a character's sprites and enable Sprite Packer Mode in Project Settings → Editor. Sprites keep their own import settings and pivots; the atlas only changes how they are stored. Godot 4 imports each PNG as its own texture and does not pack sprites automatically; for many small images you can use an AtlasTexture per region of a sheet — which is exactly what a SpriteFrames .tres does — or a texture packer before import. GameMaker always packs sprites onto texture pages; group the sprites that appear together into the same texture group so a level does not need to swap pages while it draws.
Whichever engine you use, pack by usage, not by type: one atlas for the player and their effects, one per enemy family, one for UI. That keeps memory down because only the atlases a scene actually needs are loaded.
Naming and folder conventions
A predictable naming scheme saves more time than any packing trick. Name files by character, animation and, where relevant, direction and frame count: knight_attack_strip6.png, knight_walk_down_strip4.png. Keep one folder per character, keep the source sheets out of the build folder if your engine packs atlases from separate frames, and write the frame size, fps, pivot and row order into a small readme or data file next to the art.
SpriteLab's engine pack follows this pattern for one character: a godot folder with a SpriteFrames .tres and one strip per animation in godot/sheets, a unity folder with one subfolder of numbered frames per animation, a gamemaker folder with _stripN files, a hitboxes.json with per-frame boxes, fps and loop flags, and a README.txt. A 4-direction walk is split into one strip per direction.

A layout checklist
Before importing a sheet into any engine, check:
- 01Image width divided by columns, and height divided by rows, are whole numbers.
- 02The character's feet sit on the same pixel row in every frame of the animation.
- 03The background is real transparency, not a white or checkerboard fill.
- 04No texture is larger than your target platform and the engine's import Max Size allow.
- 05Filtered or scaled art has padding or extrusion; pixel art uses nearest filtering.
- 06Row order and frame counts are written down next to the files.
Frequently asked questions
Should I use a sprite sheet or individual images?
Either works for source files. Engines pack individual images into atlases for the build, so choose whatever is easiest to edit; equal-size strips are the most portable.
How much padding should sprite sheet frames have?
Two pixels is a common default; use 4–8 if mipmaps are enabled. Pixel art drawn with nearest filtering at whole-pixel positions often needs none.
What is the maximum sprite sheet size?
4096×4096 is safe on almost all hardware including older phones; desktop GPUs accept 8192 or 16384. Unity's default import Max Size is 2048, so raise it for larger sheets.
Why do lines appear at the edges of my sprites?
Texture bleeding from neighbouring frames. Add padding or extrusion, use nearest filtering for pixel art, turn off mipmaps for 2D sprites and draw at whole-pixel positions.