Aseprite to Unity 6 — Sprites and Animation Clips
Drop the .aseprite file and export a Unity bundle: the atlas, a JSON description and a small editor script that slices the sprites (Point, uncompressed) and creates one AnimationClip per tag with its frame timing.
Unity cannot play an .aseprite file by itself: it needs sprites on a texture and an AnimationClip per animation. Drop the file into Nerulio, check its tags, and export for Unity 6: you get the packed PNG, a JSON and an editor script that, from Tools › Nerulio › Import Studio JSON, slices the texture (Point, uncompressed, pivots from your pivot slice) and writes one .anim per tag with every frame's own duration. Reverse and ping-pong tags are written out frame by frame. Checked in Unity 6000.5.3f1; Unity's own 2D Aseprite Importer package is the alternative.

- Unity 6Verified· Unity 6000.5.3f1
- .asepriteVerified· Aseprite 1.3.18
- Godot 4Verified· Godot 4.7.2
- Phaser 3 / 4Verified· Phaser 3.90 + 4.2
- PixiJS 8Verified· PixiJS 8.21
- Aseprite JSONVerified· Phaser load.aseprite · PixiJS 8.21
- 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
From Aseprite tags to Unity clips
An .aseprite file stores frames with a duration in milliseconds each, tags that name a frame range with a direction (forward, reverse, ping-pong) and a repeat count, layers, and slices that can carry a pivot. Unity's equivalent is a texture in Sprite Mode Multiple, one sprite per frame with a normalised pivot, and an AnimationClip whose keys swap the SpriteRenderer's sprite at given times.
Nerulio composites the visible layers of every frame, packs the frames and writes their rects in Unity's bottom-left coordinates. Each tag becomes a clip whose keys sit at the running sum of the frame durations, plus a closing key so the last frame lasts its full time. A tag that repeats forever gets Loop Time on; a tag with a repeat count gets Loop Time off, because a clip has no repeat count.
Unity's own 2D Aseprite Importer (version 4.x needs Unity 6.4 or later) imports the file directly and reimports it on save. According to its documentation it supports individual frame timings and turns ∞ into a looping clip, but only the Forward direction is supported and slices are not imported.
- Tag
- A named frame range in Aseprite with a direction and a repeat count.
- Pivot slice
- An Aseprite slice with a pivot point; Nerulio uses it as each frame's pivot.
- Loop Time
- The AnimationClip setting that makes a clip repeat.
- Closing key
- A final key that repeats the last sprite so it keeps its own duration.
Example: a 32 × 32 hero with three tags
Aseprite Unity 6 AnimationClip (key times, s)
idle 4 frames × 125 ms, ∞ idle.anim 0, 0.125, 0.25, 0.375 | end 0.5 loop on
attack 100, 100, 150, 250 ms, ×1 attack.anim 0, 0.1, 0.2, 0.35 | end 0.6 loop off
jump 3 frames × 80 ms, ping-pong jump.anim frames 0-1-2-1: 0, 0.08, 0.16, 0.24 | end 0.32
pivot slice at (16, 31) on the 32 × 32 canvas, frame not trimmed
Unity pivot = (16 / 32, (32 − 31) / 32) = (0.5, 0.03125) (y counts up)The ping-pong tag is written as the order 0-1-2-1, so it plays the same in Unity without relying on a direction setting.
What survives the conversion
| In Aseprite | In Nerulio | In Unity 6 |
|---|---|---|
| Frame pixels (visible layers) | Composited frame, packed into the PNG | One sprite rect of that texture |
| Frame duration (ms) | Kept per frame | Key time: each frame starts at the sum of the previous durations |
| Tag | One animation of the same name | One .anim clip of the same name |
| Direction reverse / ping-pong | Playback order written out | Keys in that order |
| Repeat ∞ | Loop | Loop Time on |
| Repeat 1, 2, 3… | Plays that many times in the preview | Loop Time off: the clip plays once |
| Pivot slice (or a pivot set with P) | Frame pivot (default bottom centre) | Sprite pivot, Custom alignment, y up |
| Hit / hurt slices | Boxes per frame | Not written for Unity (they are in the generic JSON) |
| Layers | Composited | One sprite per frame, no per-layer sprites |
What it does
- Tags become AnimationClips with each frame's duration; pivots come from Aseprite slices or the Studio's pivot tool.
- Sprite Mode Multiple, Point filter, no compression — the settings pixel art needs.
- Rects, pivots, pixels, clip keys and durations were checked in Unity 6000.5.3f1 batch mode.
- No Unity package or Aseprite importer needed on your side.
How to do it
- Drop the .aseprite file and check the tags.
- Open Pack & Export and choose Unity 6.
- Copy the bundle into Assets/ (the Editor folder with it).
- Run Tools › Nerulio › Import Studio JSON: it slices the sheet and builds the clips.
Files you get
| File | What it is for |
|---|---|
hero.png | The packed frames (Point-friendly: trimmed, 2 px apart, never rotated). |
hero.unity.json | Sprite rects in Unity coordinates, normalised pivots, and one clip per tag with each frame's milliseconds and loop flag. |
Editor/NerulioSpriteImporter.cs | The editor script: texture settings, sprite rects, .anim clips. |
README-UNITY.md | The import steps for this bundle. |
Import it into Unity 6
- Copy the bundle folder into
Assets/, PNG next to the JSON, with itsEditorsubfolder. Unity compiles the script; the 2D Sprite package must be installed (it is in every 2D template). - Run Tools › Nerulio › Import Studio JSON and pick
hero.unity.json. - Check the texture: Sprite (2D and UI), Multiple, Point (no filter), Compression None, PPU 100; the Sprite Editor shows one rect per frame with its pivot.
- Find
idle.anim,attack.animandjump.animnext to the JSON; open one in the Animation window to see its keys. - Add the clips to an Animator Controller on a GameObject with a SpriteRenderer; for a play-once tag such as
attack, add a transition back toidlewhen it ends. - Keep the
.asepritefile itself out ofAssets/if Unity's Aseprite Importer package is installed, or Unity imports it a second time its own way.
Check the result
attack.animhas keys at 0, 0.1, 0.2 and 0.35 s and ends at 0.6 s, the total of the tag in Aseprite.- Loop Time is on for
idleand off forattack. - Play
jumpnext to Aseprite's preview: the order 0-1-2-1 and the 80 ms steps match. - Switch clips: the feet stay on the pivot point.
Troubleshooting
| Symptom | Likely cause | How to check | Fix |
|---|---|---|---|
| A clip plays once instead of looping | The tag has a repeat count in Aseprite (anything but ∞) | Loop Time in the clip's Inspector | Set the tag to ∞ and export again, or tick Loop Time in Unity |
| Console: "clip … names a missing sprite" | The PNG was renamed or moved away from the JSON before importing | Is the PNG next to the JSON with its exported name? | Keep the files together and run the import again |
| The sprite is blurry | Filter Mode or compression was changed after the import | Texture Inspector | Point (no filter) and Compression None; see blurry pixel art in Unity |
| The character jumps between frames | No pivot slice, so each frame uses the default bottom centre, or pivots differ per frame | Sprite Editor: pivot markers across frames | Add one pivot slice in Aseprite or set pivots with P in Nerulio; see the pivot editor |
| Two copies of every sprite appear | Unity's Aseprite Importer also imported the .aseprite file placed in Assets/ | Project window shows the .aseprite asset expanded | Use one route: remove the .aseprite from Assets/, or skip this bundle |
| A ping-pong tag plays only forwards | That is Unity's own importer (forward only), not this bundle | Which asset does the Animator use? | Use the .anim from this bundle, which has the order written out |
Other ways to do it
| Option | When it is the better choice |
|---|---|
| Unity's 2D Aseprite Importer package | You edit in Aseprite all day and want Unity to reimport on save, with per-layer import; accept forward-only tags and no slices. |
| Export a PNG sheet from Aseprite and slice it in the Sprite Editor | One or two animations at an even frame rate; see slicing a sprite sheet in Unity. |
| The same file for another engine | Aseprite to Godot or Aseprite to Phaser. |
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.
| Target | Files | Check |
|---|---|---|
| Godot 4 | .tres SpriteFrames · .tscn AnimatedSprite2D · .png.import | Verified 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 · AnimationClip | Verified Unity 6000.5.3f1Batch mode: sprite rects, pivots, pixels, clip keys and durations checked. |
| Phaser 3 / 4 | atlas JSON (multiatlas) · .anims.json | Verified Phaser 3.90 + 4.2Frames and animations drawn by both versions. |
| PixiJS 8 | spritesheet JSON · animations · anchor · meta.scale | Verified PixiJS 8.21Rotated and multi-page atlases included. |
| Aseprite JSON | hash / array · frameTags · slices | Verified Phaser load.aseprite · PixiJS 8.21Tags keep their direction and repeat count. |
| .aseprite | layers · tags · durations · slices | Verified Aseprite 1.3.18Opened and rendered by the Aseprite command line. |
| Spine / libGDX | .atlas | Verified spine-canvas 4.2Every region drawn by the Spine runtime, rotated and trimmed; libGDX itself was not run. |
| Starling / Sparrow XML | XML per page | Verified 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ÖVE | Lua quads · nerulio_atlas.lua · main.lua | Verified LÖVE 11.5Every frame drawn and every animation stepped through the shipped helper. |
| Defold | .atlas · .tilesource | Built Defold bob.jar 1.13.1Built by Defold's command-line builder; the built texture's UVs were read back. |
| GameMaker | spr_<name>_stripN.png · gamemaker.json | UNVERIFIEDNot loaded in GameMaker (no headless GameMaker). The strips are cut the way its strip importer cuts them. |
| CSS sprites | .css · preview .html | Verified ChromiumEvery class drawn from the shipped stylesheet. |
| GIF / APNG | one file per animation | Decoded 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
- Layers arrive flattened into one sprite per frame.
- A repeat count above one is not kept: the clip plays once.
- Hit and hurt boxes are not written for Unity.
- 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
Nerulio's Unity bundle was checked in Unity 6000.5.3f1 batch mode (sprite rects, pivots, pixels, Point / Uncompressed / Multiple, clip keys and times); clips playing through an Animator at runtime were not checked. The .aseprite reader reopened 231 real files in Aseprite 1.3.18 with the same tags, durations and pixels. What is said about Unity's own Aseprite Importer comes from its version 4.0 documentation.
Official documentation used
Questions
Why not Unity's own Aseprite importer?
You can use it. This route gives a packed atlas and clips from the same timing, and it works on machines without the importer package.
Does it keep one pivot per frame?
Yes, each sprite rect gets its frame's pivot (a common anchor when the frames share one).
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).