Sprite Sheet Metadata Explained: Unity JSON vs Godot vs Generic
What each export format contains, how engines use it, and when to choose generic JSON vs engine-specific.
Sprite sheet metadata describes where each frame lives in the texture (x, y, width, height) and sometimes pivot, duration, or trim. Every engine expects a slightly different format. This post explains the main ones—Unity, Godot, Phaser, PixiJS, and generic—and when to use generic JSON vs engine-specific so you can pick the right export and avoid conversion headaches.
Unity
Unity's Sprite Editor can use a JSON that lists frames with rect, pivot, border, and name. The rect is in pixels (x, y, width, height). Pivot is often normalized (0–1). When you export "Unity" from a tool, it should match this shape so that an import script or the editor can slice the texture automatically.
Unity's expected structure often includes a "frames" array where each element has a filename or id, a "rect" object with x, y, w, h, and "pivot" with x and y. Border is used for 9-slice. An import script reads this JSON and populates the texture's SpriteMetaData array before applying the Sprite Editor. Keeping the export format in sync with what your script expects avoids runtime conversion and bugs.
Unity fields at a glance
Per frame: rect (x, y, w, h in pixels), pivot (x, y often 0–1), name (string), optional border for 9-slice. The texture path or name is usually at the top level. Your import script maps these to SpriteMetaData and calls Apply().
Godot
Godot's atlas format typically describes the texture path and a list of regions (name, rect). Godot doesn't always auto-import arbitrary JSON; you may need to create AtlasTexture resources from the JSON in a script. The rect is usually x, y, width, height in pixels.
Godot may expect a specific key structure (e.g. "regions" or "frames") and rect format. If your tool exports a different shape, a small conversion script or import plugin can map your JSON to AtlasTexture creation. Storing frame names in the metadata makes it easier to build animations by name in the Godot editor. Document the exact format your pipeline uses so that switching tools or versions doesn't break the import.
Phaser / PixiJS / Generic
Phaser and PixiJS accept JSON that maps frame names to rects (and optionally frame duration, anchor, etc.). "Generic" JSON is usually a simple list of frames with id/name and rect, which any custom loader can read. Use generic when you're writing your own loader or when the engine isn't one of the built-in targets.
Phaser's atlas format (e.g. Hash or Array) includes a "frames" object where each key is a frame name and the value has frame (rect), sourceSize, and optionally duration. PixiJS has similar expectations. Generic JSON might be a flat array of { "id": "frame_0", "x": 0, "y": 0, "width": 64, "height": 64 }. A custom loader can iterate this array and register frames with the engine. Adding duration or pivot to generic JSON makes it more useful across engines without locking you into one format.
Choosing a Format
Use the format that matches your engine so you don't have to transform the data by hand. If you're building a custom engine or a plugin, start with generic JSON and add fields as needed (duration, pivot, etc.) and keep the tool's export in sync.
When in doubt, export generic JSON plus an engine-specific option if your tool supports it. That way you have one canonical format for tooling and scripts, and a convenience format for the primary engine. Version or document the JSON schema so that future changes don't silently break importers. If you only ever target one engine, exporting that engine's format directly is the simplest and avoids a conversion step.
Summary
Unity expects rect, pivot, and optionally border and name. Godot expects texture path and regions; script to AtlasTexture if needed. Phaser/PixiJS use frame names and rects; generic JSON is a flexible fallback. Choose the format that matches your engine or pipeline and keep the export and importer in sync.