Skip to content

Sprite Sheet Editor — Slice, Animate, Export to Engines

One workspace for the whole sprite pipeline: import any sheet, GIF or .aseprite file, turn it into tagged animations with per-frame durations, pivots and boxes, and export files that were loaded in the engines themselves.

The Sprite workspace is the step between finished art and a game engine. It imports a PNG sheet, numbered frame files, a GIF or APNG, an .aseprite file or an existing atlas with its JSON or XML, and turns it into animations (tags) with a duration in milliseconds on every frame, a pivot per frame and hit, hurt or custom boxes. Pack & Export then writes the files Godot 4, Unity 6, Phaser, PixiJS, LÖVE and other targets load. Painting pixels happens in the Pixel workspace of the same project.

Drop a sprite sheet, numbered frames, a GIF / APNG or an .aseprite file
Runs in your browser. Files are not uploaded.
Studio Sprite workspace: one frame with its pivot, a hit box and a hurt box, and the timeline with animation tags
The real Studio with a CC0 asset (OpenGameArt).
Exports to
  • Godot 4Verified· Godot 4.7.2
  • Unity 6Verified· Unity 6000.5.3f1
  • Phaser 3 / 4Verified· Phaser 3.90 + 4.2
  • PixiJS 8Verified· PixiJS 8.21
  • Aseprite JSONVerified· Phaser load.aseprite · PixiJS 8.21
  • .asepriteVerified· Aseprite 1.3.18
  • Spine / libGDXVerified· spine-canvas 4.2
  • Starling / Sparrow XMLVerified· Phaser 4.2
  • LÖVEVerified· LÖVE 11.5
  • DefoldBuilt· Defold bob.jar 1.13.1
  • GameMakerUNVERIFIED
  • CSS spritesVerified· Chromium
  • GIF / APNGDecoded· Pillow

What a game-ready sprite needs besides pixels

An engine does not play a picture; it plays a list of frames. Each frame needs its rectangle on a texture, the canvas it belongs to (so a trimmed frame lands where it was drawn), a pivot that says which pixel sits on the object's position, and a duration. An animation is a named run of frames with a direction and a repeat count. Hit and hurt boxes are extra rectangles per frame that game code checks.

The Studio keeps exactly that document. A sheet is one shared image and its frames are regions of it, so reordering or re-tagging never touches pixels. A pivot is stored as 0–1 of the frame canvas (bottom-centre 0.5, 1.0 unless you set it), durations are milliseconds (100 by default, as in Aseprite), and a tag's repeat follows Aseprite: 0 loops, n plays n times. Every automatic guess on import is listed with its confidence and one-click alternatives, and Apply is one undo step.

Each export target writes what its engine can read and says what it cannot carry: Godot gets per-frame durations and boxes in resource metadata, Unity gets per-frame pivots and one clip per tag but no boxes, Defold plays one FPS per animation.

Tag
A named run of frames with a direction (forward, reverse, ping-pong) and a repeat count.
Pivot
The point of a frame that sits on the object's position; stored as 0–1 of the frame canvas.
Frame canvas
The full size a frame is drawn on, even when only its opaque part is packed.

Example: one 384 × 256 sheet to a Godot 4 bundle

A sheet of 8 columns × 4 rows of 48 × 64 frames, one move per row.

Import     grid 48 × 64, margin 0, gap 0 · 32 frames · one animation per row
Timeline   rows renamed idle, run, jump, attack
idle       8 × 100 ms = 800 ms, repeat 0 (loop)
attack     7 × 100 ms + frame 5 held 250 ms = 950 ms, repeat 1 (plays once)
Pivot      bottom-centre (0.5, 1.0) = pixel (24, 64) on every frame
Hit box    attack frames 4–6: 16 × 12 px at (34, 30), same box id on all three
Export     Godot 4 → hero.tres (4 animations) + hero.png + hero.tscn + hero.png.import
           attack in Godot: loop off; idle: loop on

The same project exports again for Unity or Phaser without redoing the timeline. What happens in Godot next is on Aseprite to Godot and sprite sheets in Godot.

What it does

  • Imports sheets, numbered frame files, GIF and APNG (every frame and delay), .aseprite (layers, tags, durations, slices), Aseprite JSON, TexturePacker JSON and Starling XML.
  • An Aseprite-style timeline: tags with direction and repeat, per-frame durations, reorder, duplicate, flip.
  • Playback with loop, ping-pong and repeat, onion skin and a floating preview at 1×–8×.
  • Pivots, hit / hurt / custom boxes and collision polygons per frame, tag or selection.

How to do it

  1. Drop your sheet, frames or .aseprite file here.
  2. Apply the import (or pick one of the alternatives it lists).
  3. Name animations on the timeline, set durations, pivots and boxes.
  4. Open Pack & Export, choose your engine and export.

Check the result

  • Play every tag with Enter before export; each frame shows for its own milliseconds, and a play-once tag stops on its last frame.
  • In Pack & Export read the line under the target: "Loaded in Godot 4.7.2" (or UNVERIFIED in amber for GameMaker) and any setting the target changes before export.
  • After export read the notes: they list what the target could not carry, such as differing pivots in one Godot animation or boxes that Unity does not receive.
  • Open the result in the engine and play one tag next to Nerulio's preview at the same zoom.

Troubleshooting

SymptomLikely causeHow to checkFix
The proposed grid is wrongUneven gaps, or sprites of mixed sizes on a sheet that looks like a gridThe decision shows medium or low confidence, with reasons about split or crossed cellsPick an alternative or Islands; see slicing that is off
An .aseprite file arrives flattenedIts layers do not compose exactly in the Studio (5 of 231 test files), or cels use z-index (4 of 231)The import panel states the reasonFrames and timing are still right; keep layered editing in Aseprite and re-import
Boxes or pivots are missing in the engineThe target has no place for them: Unity gets pivots but no boxes, Defold and CSS get neitherThe export notes under the buttonExport the Godot bundle or the generic JSON for boxes, or add them in the engine
The character hops when the animation changesFrames have different pivots but the Godot scene node has one offsetThe Godot export notes warn about differing pivotsUse one pivot for the tag, see pivots per frame

Other ways to do it

OptionWhen it is the better choice
Aseprite, then its File › Export Sprite Sheet and an engine pluginYou draw and animate in Aseprite anyway and your engine has a maintained importer; plugins that call Aseprite need it installed on every machine that imports.
TexturePackerYou mainly pack many separate images into atlases for many frameworks and want its command-line automation; it does not edit tags, pivots per frame or boxes the way a sprite editor does.
The engine's own editors (Unity Sprite Editor, Godot SpriteFrames panel)One or two animations with even timing that you prefer to set up inside the project.

Engine exports and how each was checked

"Verified" means the exported files were loaded by the real engine or tool on real CC0 assets and the result was compared with the source. Anything that was not loaded is labelled as such.

TargetFilesCheck
Godot 4.tres SpriteFrames · .tscn AnimatedSprite2D · .png.importVerified Godot 4.7.2Loaded by Godot; every animation frame drawn and compared with the source file. The scene uses Nearest filtering; rotation is never used.
Unity 6.unity.json · Editor/NerulioSpriteImporter.cs · AnimationClipVerified Unity 6000.5.3f1Batch mode: sprite rects, pivots, pixels, clip keys and durations checked.
Phaser 3 / 4atlas JSON (multiatlas) · .anims.jsonVerified Phaser 3.90 + 4.2Frames and animations drawn by both versions.
PixiJS 8spritesheet JSON · animations · anchor · meta.scaleVerified PixiJS 8.21Rotated and multi-page atlases included.
Aseprite JSONhash / array · frameTags · slicesVerified Phaser load.aseprite · PixiJS 8.21Tags keep their direction and repeat count.
.asepritelayers · tags · durations · slicesVerified Aseprite 1.3.18Opened and rendered by the Aseprite command line.
Spine / libGDX.atlasVerified spine-canvas 4.2Every region drawn by the Spine runtime, rotated and trimmed; libGDX itself was not run.
Starling / Sparrow XMLXML per pageVerified Phaser 4.2Phaser 3.90 draws trimmed XML frames wrongly (its own bug); the "Sparrow XML (Phaser 3)" preset turns trim off and passes in 3.90 and 4.2.
LÖVELua quads · nerulio_atlas.lua · main.luaVerified LÖVE 11.5Every frame drawn and every animation stepped through the shipped helper.
Defold.atlas · .tilesourceBuilt Defold bob.jar 1.13.1Built by Defold's command-line builder; the built texture's UVs were read back.
GameMakerspr_<name>_stripN.png · gamemaker.jsonUNVERIFIEDNot loaded in GameMaker (no headless GameMaker). The strips are cut the way its strip importer cuts them.
CSS sprites.css · preview .htmlVerified ChromiumEvery class drawn from the shipped stylesheet.
GIF / APNGone file per animationDecoded PillowEvery frame and delay decoded again after export; APNG is exact.

Evidence

GIF decoder: 408 of 408 frames identical to Pillow on 29 real GIFs; APNG 132 of 132 on 16 files. .aseprite: 231 corpus files imported, re-written and reopened in Aseprite 1.3.18 with the same tags, durations and pixels (231/231). Exports: 49 runs in the real engines on real CC0 assets, 47 pass — the 2 failures are Phaser 3.90's trimmed-XML bug, which the Phaser 3 preset avoids.

Limits

  • Rotated frames from an imported atlas stay rotated, and exporting them is UNVERIFIED; repack without rotation.
  • GameMaker strips are not verified in GameMaker itself.
  • Painting tools live in the Pixel workspace, which lacks some Aseprite tools (layer groups, tilemap layers, RotSprite, text).
  • A grid or island guess is a preview with a confidence; nothing is cut until you press Apply, and every choice has one-click alternatives.
  • .aseprite files whose layers do not compose exactly (e.g. group opacity) are imported flattened, and the Import panel says why.
  • Rotated frames in an imported atlas stay rotated; their export is UNVERIFIED.
  • Images up to 32,768 px per side (268 million pixels), subject to your browser's memory.

Versions and sources

Import: frames correct on 16 of 16 real assets with the default choices; 231 of 231 .aseprite files came back from Nerulio's writer into Aseprite 1.3.18 with the same tags, durations and pixels. Export: 47 of 49 engine runs pass (Godot 4.7.2, Unity 6000.5.3f1, Phaser 3.90 and 4.2, PixiJS 8.21, LÖVE 11.5, Spine runtime 4.2, Defold bob.jar 1.13.1); the two failures are Phaser 3.90's bug with trimmed Sparrow XML, which the Sparrow XML (Phaser 3) preset avoids.

Official documentation used

Classic tool

Outline, de-fringe and a ZIP of frame PNGs are still in the classic Sprite Lab.

Open the classic tool →

Questions

How is this different from Aseprite?

This workspace is the step between your art and the engine: slicing, timing, pivots, boxes, packing and engine files, and it reads and writes .aseprite. Painting is in the Pixel workspace of the same project, which has the core Aseprite tools but not all of them.

Does it keep my Aseprite tags and durations?

Yes. On the 231-file .aseprite test corpus, tags and durations came back 231/231 when the Studio's output was opened in Aseprite 1.3.18.

Is it free, and do I need an account?

Everything on these pages is free and works without an account. There is no watermark and no export that is held back.

Are my sprites uploaded?

No. The Studio decodes, packs and exports in this browser tab. Projects are autosaved in the browser (IndexedDB) and can be saved as a .nerulio file.

Does it need Aseprite or an engine plugin installed?

No. .aseprite files are read and written in the browser, and each engine bundle carries what that engine needs (for Godot, the import settings and scene; for Unity and the Godot TileSet, a small editor script).