本文へスキップ

スプライトシート作成 · フレームをアトラスにパック

フレーム画像・GIF・.asepriteを入れると、設定を変えるたびにワーカーで即座に再パックされた密なスプライトシートと、エンジンが読むデータファイルが得られます。

スプライトシートは多数のフレームを1枚の画像にまとめ、ゲームがテクスチャを何十枚も読まずに済むようにします。詰めてパックしたアトラスには、フレームごとの名前と矩形を書いたデータファイルが付きます。連番PNG、GIF、.asepriteファイルを入れてエンジンのプリセットを選ぶと、Nerulioがブラウザ内でパックし(既定:MaxRects、トリムあり、間隔2px)、そのエンジンが読むデータファイルと一緒にPNGを書き出します。セルがすべて同じ大きさの単純なグリッドシートは、下にリンクした従来の作成ツールを使ってください。

パックするフレーム画像、GIF、.asepriteファイルをドロップ
空のStudioを開く
ブラウザ内で処理し、ファイルはアップロードされません。
Studio のパック&書き出し:各フレームの枠が表示されたアトラスページ、使用率、書き出し先
CC0アセット(OpenGameArt)を開いた実際のStudio画面です。
書き出し先
  • Godot 4検証済み· Godot 4.7.2
  • Unity 6検証済み· Unity 6000.5.3f1
  • Phaser 3 / 4検証済み· Phaser 3.90 + 4.2
  • PixiJS 8検証済み· PixiJS 8.21
  • Aseprite JSON検証済み· Phaser load.aseprite · PixiJS 8.21
  • .aseprite検証済み· Aseprite 1.3.18
  • Spine / libGDX検証済み· spine-canvas 4.2
  • Starling / Sparrow XML検証済み· Phaser 4.2
  • LÖVE検証済み· LÖVE 11.5
  • Defoldビルド確認· Defold bob.jar 1.13.1
  • GameMaker未検証
  • CSS sprites検証済み· Chromium
  • GIF / APNGデコード確認· Pillow

グリッドシートとパック済みアトラス

グリッドシートは全フレームに同じ大きさのセルを割り当てます。そのためエンジンは計算だけでn番目のフレームを見つけられます。列 = n mod 列数、行 = n ÷ 列数(切り捨て)。データファイルは不要ですが、どのセルも一番大きなフレームの大きさになり、透明な余白もそのまま保存されます。

パック済みアトラスは各フレームを見えるピクセルだけに切り詰め、空いた場所に詰め込みます。位置を計算では求められないので、パッカーがデータファイルを書きます。フレーム名、ページ上の保存位置(frame)、元のキャンバス上の位置(spriteSourceSize)、元のキャンバスの大きさ(sourceSize)、90度回して保存したか(rotated)です。エンジンはこの数値で元の大きさの枠内に描くので、トリムしたフレームも位置がずれません。

縁を守る設定が2つあります。シェイプ間隔はフレームの間に透明ピクセルを空け、押し出し(extrude)はフレームの最も外側のピクセルを周りに複製します。テクスチャフィルターが縁のすぐ外を読んでも、隣のフレームではなく同じ色を読むようになります。回転は面積を少し減らしますが、回転したフレームを戻して描けるエンジンは一部だけです。Nerulioのプリセットは、エンジン検証で正しく描かれたPixiJSとSpineでのみ回転を許可します。

ページ
アトラス画像1枚。最大サイズに収まらないフレームは次のページへ(最大64枚)。
トリム
フレームの透明な余白を切り取り、オフセットを記録すること。元の位置に描かれます。
シェイプ間隔(shape padding)
フレーム間の透明ピクセル。既定は2px。
押し出し(extrude)
フレームの縁のピクセルを外側に複製した帯。既定は0、LÖVEプリセットは1。
エイリアス
見えるピクセルが同一のフレームは、保存領域を1つ共有します。

例:40 × 29の走りフレーム6枚

CC0の忍者の走りモーション6フレーム(各40 × 29px、大半が透明)を、NerulioのPhaserプリセット(トリムあり、間隔2、回転なし)でパックし、ほかの並べ方と比べました。

並べ方                           ページ      面積        横一列比
横一列、6 × 40px                 240 × 29    6,960 px²   100 %
パック、トリムなし、間隔2          82 × 91    7,462 px²   107 %
パック、トリムあり、間隔2          38 × 50    1,900 px²    27 %
パック、トリムあり、回転あり       33 × 57    1,881 px²    27 %

見えるピクセル(バウンディングボックス6個の合計) 1,591 px²
トリム版ページの使用率           1,591 / 1,900 = 0.84

"run_0": { "frame": {"x":0,"y":34,"w":18,"h":15},
           "spriteSourceSize": {"x":10,"y":10,"w":18,"h":15},
           "sourceSize": {"w":40,"h":29}, "rotated": false, "trimmed": true }

run_0は18 × 15ピクセルだけが保存されます。エンジンはこの断片を40 × 29の枠の中で右へ10px、下へ10pxずらし、元の位置に描きます。節約できたのはトリムのおかげです。トリムなしでパックすると、フレーム間の間隔のぶん横一列より少し大きくなります。

できること

  • MaxRects(5種のルール)、Skyline、Guillotine。「すべて試す」で最小のページを採用。
  • オフセットを保つトリム、同一フレームの重複除去、縁の拡張、外枠・図形の余白、POT・正方形・固定サイズ、最大64ページ。
  • ニアレストネイバーで@0.5x〜@4xの倍率違い、乗算済みアルファも選択可。
  • 色が正確なPNG:フレームをCanvasを通さずJavaScriptでデコードするので、色とアルファがずれません(インターレースPNGはブラウザのデコーダーを使い、その旨を表示)。

使い方

  1. フレーム(連番PNGのフォルダーも可)やGIF・.asepriteを入れる。
  2. エンジンのプリセットを選ぶと、アトラスがその場で再パック。
  3. 使用率・ページ数・フレーム一覧を確認し、必要ならトリム・余白・サイズを変更。
  4. エンジン向けに書き出し。

エンジンごとに受け取るファイルと、シートの読み込み方

PNGは必ずデータファイルの隣に置いてください。データ側が画像名を持っています(JSONのmeta.image、XMLのimagePath、Spine .atlasのページ行)。

ファイル用途
run.png + run.json (Phaser 3 / 4)this.load.atlas("run", "run.png", "run.json")のあとthis.add.sprite(x, y, "run", "run_0")。詳しくはPhaserアトラスのページ。
run.png + run.json (PixiJS 8)const sheet = await Assets.load("run.json")のあとsheet.textures["run_0"]またはsheet.animations["run"]。PixiJSのスプライトシートJSONを参照。
run.tres + run.tscn (Godot 4)アトラスの代わりに、そのまま使えるSpriteFramesリソースとシーン。Godotでスプライトシートを参照。
run.unity.json + importer script (Unity 6)エディタースクリプトがテクスチャを切り分け、クリップを作ります。Unityでスプライトシートを参照。
run.lua, run.atlas, run.xml, run.cssLÖVEのQuad、Defold・Spineのアトラス、Sparrow XML、CSSクラス:LÖVE、Defold、Spine、CSSスプライト。

結果の確認

  • パック&書き出しの使用率を見ます。0.84はページの84%が見えるフレーム面積という意味です。低いときは、たいていトリムがオフか、1枚だけ極端に大きなフレームがあります。
  • パック済みフレーム一覧の行にカーソルを合わせると、キャンバス → 保存サイズ、ページ、トリム・回転・「同じフレーム」(エイリアス)の印が出ます。
  • エンジンで、トリムしたフレームをトリムしていない隣のフレームと同じ点に描きます。ずれるならローダーがspriteSourceSizeを無視しています(トラブルシューティング参照)。

トラブルシューティング

症状考えられる原因確認方法対処
アニメーション再生中にフレームが跳ねる・揺れるトリムしたフレームをオフセットなしで描いている。ローダーやコードがframeだけを使いspriteSourceSize・sourceSizeを無視トリム量の違う2フレームを同じ点に描く。そろえば正常トリム情報を読むローダーを使うか、トリムなしでパック(ページは大きくなる)。トリム後の揺れを参照
拡大時や小数ピクセルの移動時に、フレームの縁に細い線や色のにじみテクスチャフィルターがフレームのすぐ外(隣のフレームか透明な間隔)を読んでいる縁を拡大し、線が隣の色か、透けているかを見るシェイプ間隔を2以上に保ち、押し出し1を追加、ドット絵は最近傍フィルター。アトラスの間隔を参照
一部のフレームが横倒し・反転・欠ける回転したフレームを戻さないエンジンやローダーなのに回転を許可したその項目に"rotated": trueがある回転なしでパック。NerulioのGodot・Unity・Phaser・LÖVE・XML・CSS書き出しは回転したパックを拒否する
スプライトがページに収まらないというエラー間隔と押し出しを足したフレーム1枚が最大ページより大きいメッセージにフレーム名とサイズが出る最大サイズを上げる(最大16384px)、エンジンが読めるなら回転を許可、またはそのフレームを縮小

ほかの方法

方法こんなときに向いています
単純なグリッドシート(下の従来の作成ツール)全フレームが同じ大きさで、エンジンがセル単位で切り出すとき。例:GameMakerのストリップ、GodotのAdd Frames from Sprite Sheet。同期させるデータファイルがありません。
Aseprite自体のシート書き出し(コマンドラインの--sheet-pack、--trim、--merge-duplicates)絵をAsepriteで管理し、タグと長さ入りのJSONだけあればよいとき。Godot SpriteFramesのようなエンジン用バンドルは作りません。
TexturePacker Proポリゴンパッキング、GPUテクスチャ形式、ビルドパイプライン用のコマンドラインが必要なとき。Nerulioとの計測比較はTexturePacker代替のページ。
エンジン自身のパッカー(Defoldアトラス、Spineのテクスチャパッカー)エンジンがビルドや書き出しの時に個別画像をどのみちパックするとき。フレーム画像だけあれば足ります。シートをPNGフレームに分割を参照。

エンジン別の書き出しと検証方法

「検証済み」は、実際のCC0アセットから書き出したファイルを本物のエンジン・ツールで読み込み、元データと比較したという意味です。読み込んでいない形式はそのように表示します。

書き出し先ファイル検証
Godot 4.tres SpriteFrames · .tscn AnimatedSprite2D · .png.import検証済み Godot 4.7.2Godotで読み込み、全アニメーションフレームを描画して元ファイルと比較。シーンはNearestフィルターで、回転は使いません。
Unity 6.unity.json · Editor/NerulioSpriteImporter.cs · AnimationClip検証済み Unity 6000.5.3f1バッチモードでスプライト範囲・ピボット・ピクセル・クリップのキーと長さを確認。
Phaser 3 / 4atlas JSON (multiatlas) · .anims.json検証済み Phaser 3.90 + 4.2両バージョンでフレームとアニメーションを描画。
PixiJS 8spritesheet JSON · animations · anchor · meta.scale検証済み PixiJS 8.21回転・複数ページのアトラスも確認。
Aseprite JSONhash / array · frameTags · slices検証済み Phaser load.aseprite · PixiJS 8.21タグの方向と繰り返し回数を保持。
.asepritelayers · tags · durations · slices検証済み Aseprite 1.3.18Asepriteのコマンドラインで開いて描画。
Spine / libGDX.atlas検証済み spine-canvas 4.2Spineランタイムで回転・トリム領域をすべて描画。libGDX本体は未実行。
Starling / Sparrow XMLXML per page検証済み Phaser 4.2Phaser 3.90はトリムされたXMLフレームを誤って描画します(Phaser側の不具合)。「Sparrow XML (Phaser 3)」プリセットはトリムを切り、3.90・4.2とも合格。
LÖVELua quads · nerulio_atlas.lua · main.lua検証済み LÖVE 11.5同梱ヘルパーで全フレームを描画し、全アニメーションを再生。
Defold.atlas · .tilesourceビルド確認 Defold bob.jar 1.13.1Defoldのコマンドラインビルダーでビルドし、生成テクスチャのUVを読み戻して確認。
GameMakerspr_<name>_stripN.png · gamemaker.json未検証GameMakerでは読み込んでいません(ヘッドレス実行不可)。ストリップはGameMakerの取り込み方式どおりに切ります。
CSS sprites.css · preview .html検証済み Chromium同梱スタイルシートで全クラスを描画。
GIF / APNGone file per animationデコード確認 Pillow書き出し後に全フレームと遅延を再デコード。APNGは完全一致。

検証の根拠

書き出し:実在のCC0アセットで実際のエンジンを49回実行し47回合格。失敗2回はPhaser 3.90のトリムXMLの不具合で、Phaser 3プリセットで回避。実在の5フレームセットでパッカー比較(CodeAndWeb無料Webパッカー、GAPTools、free-tex-packer):回転ありで5つすべて最小、回転なしで5つ中4つ。全フレームがピクセル単位で復元できます。

制限

  • ポリゴン(メッシュ)パッキングはありません。検証したエンジンのどれも、書き出しデータからメッシュアトラスを描画しないためです。
  • GameMakerのストリップはGameMaker本体では未検証です。
  • 拡大縮小バリエーション(@0.5x〜@4x)はニアレストネイバーのみです。
  • トリムしたStarling XMLはPhaser 3.90で正しく描画されないため、「Sparrow XML (Phaser 3)」プリセットを使ってください。

バージョンと出典

上のサイズは、リポジトリのテスト用コーパスにある忍者6フレームをNerulioのパッカーで処理した実際の出力で、2026-09-23の比較計測と同じ数値です。書き出したファイルはGodot 4.7.2、Unity 6000.5.3f1、Phaser 3.90と4.2、PixiJS 8.21、spine-canvas 4.2、LÖVE 11.5で読み込み、DefoldのファイルはDefoldのbob.jar 1.13.1でビルドしました。ほかのツールのオプション名は各公式ドキュメントに従います。

参照した公式ドキュメント

従来のツール

セル固定の均一グリッドシート(行×列)は従来のスプライトシート作成で作れます。

従来のツールを開く →

よくある質問

行×列の単純なグリッドシートも作れますか?

Studioは密にパックします。セルサイズ固定の均一グリッドは、下のリンクの従来のスプライトシート作成で作れます。

フレームはピクセル単位で正確ですか?

はい。実在の5つのフレームセットで、アトラスから復元した全フレームが元ファイルとピクセル単位で一致しました。

無料ですか?アカウントは必要ですか?

このページの機能はすべて無料で、アカウントなしで使えます。透かしや制限された書き出しはありません。

スプライトはアップロードされますか?

いいえ。Studioはこのブラウザのタブ内でデコード・パック・書き出しを行います。プロジェクトはブラウザ(IndexedDB)に自動保存され、.nerulioファイルとして保存できます。

Asepriteやエンジンのプラグインは必要ですか?

いいえ。.asepriteファイルはブラウザで読み書きします。エンジン別のバンドルには必要なものが入っています(Godotはインポート設定とシーン、UnityとGodotのタイルセットは小さなエディタースクリプト)。