9スライスエディター · Godot・Unity向けナインパッチ境界
境界は元画像のピクセル単位の4つの数値です。エディターは同一の列・行が最も長く続く区間から値を提案し、ドラッグ・入力・微調整ができ、すべての目標サイズを四隅が変わらないように描画します。
ナインスライス(9パッチ)の境界は元画像のピクセル単位の4つの数値(左・右・上・下)で、画像を3 × 3のグリッドに分けます。四隅は常に元の大きさで描かれ、上下の辺は横方向だけ、左右の辺は縦方向だけ伸びるか繰り返され、中央は両方向に変わります。ここで境界を一度決め(同一の列・行から提案)、好きなサイズでプレビューし、同じ数値をGodot 4(NinePatchRect.patch_margin_*)、Unity(Sprite Editorの境界とImage Type Sliced)、Phaser(add.nineslice)に入れます。出力はPNG + nine-slice.json + SETUP.mdで、エンジン内での描画は実行していません。

- Nine-slice測定確認· Pillow
- Bitmap font測定確認· independent .fnt parser
- Button states測定確認· Pillow
- Engine import未検証
9つの領域と、それぞれの役割
W × Hの画像に境界L・R・T・Bを付けると、四隅(L × T、R × T、L × B、R × B)、幅W − L − Rの上下の辺、高さH − T − Bの左右の辺、そして中央ができます。パネルのサイズを変えると、四隅はそのままコピーされ、横の辺は幅だけ、縦の辺は高さだけ、中央は両方が変わります。だから丸い角や面取りした角はどのサイズでも保たれ、四隅がすべて欠けずに見える最小サイズは(L + R) × (T + B)です。
引き伸ばし(Stretch)は辺や中央を新しい長さにリサンプリングするので、単色や反対軸方向のグラデーションに向きます。タイル(Tile)は元の大きさで繰り返すので、模様(リベット、ステッチ、レンガの縁)がゆがみません。Nerulioは最後の1枚を切り取ります。Godot 4には各タイルが欠けずに見えるよう少し伸ばすTile Fitもありますが、Nerulioのプレビューはこのモードを描きません。
同じ4つの数値を、エンジンごとに別の名前と順序で保存します。Godot 4はNinePatchRectのpatch_margin_left/right/top/bottom(整数、ピクセル)とStyleBoxTextureのtexture_margin_*。UnityのSprite EditorにはL・R・T・Bの欄がありますが、スクリプトの値Sprite.borderは左・下・右・上の順のVector4です。PhaserのNineSliceはサイズの後にleftWidth, rightWidth, topHeight, bottomHeightを受け取り、左右の幅だけを渡すと3スライスになります。
- 境界(patch margin)
- 画像の端から切り分け線までの距離(元画像のピクセル)。
- 引き伸ばし(Stretch)
- 辺や中央を新しい長さに合わせて拡大縮小する。
- タイル(Tile)
- 辺や中央を元の大きさのまま繰り返す。
- 最小サイズ
- (L + R) × (T + B)。これより小さいと四隅を欠けずに描けず、つぶれます。
例:48 × 48のパネルを300 × 80で描く
境界はすべての辺で12pxです。エディターの描画プランが作る矩形で、書き出すプレビューも同じプランを使います。
元画像 48 × 48 境界 L 12 · R 12 · T 12 · B 12 目標 300 × 80 引き伸ばし
四隅 4 × (12×12 → 12×12) 1:1でコピー、リサンプリングなし
上/下 24×12 → 276×12 276 = 300 − 12 − 12 (横方向だけ×11.5)
左/右 12×24 → 12×56 56 = 80 − 12 − 12 (縦方向だけ×2.33)
中央 24×24 → 276×56
タイル 上の辺 = 24pxのタイル11枚 + 切り取った12pxの1枚 (11 × 24 + 12 = 276)
小さすぎ 目標 20 × 80:20 < 12 + 12 → 四隅が10 + 10につぶれる(警告 "narrow")
非対称 L 10 · R 6 · T 8 · B 14 → Unity Sprite.border (x, y, z, w) = (L, B, R, T) = (10, 14, 6, 8)
Godot patch_margin_left 12 · right 12 · top 12 · bottom 12
Phaser this.add.nineslice(x, y, "panel", null, 300, 80, 12, 12, 12, 12)整数倍率2なら四隅はちょうど24 × 24(元の1ピクセルが2 × 2)で描かれ、ピクセルアートの枠が2倍でもくっきりしたままです。
できること
- 同一の列・行から境界を提案。根拠の区間を表示し、勝手に適用しません。
- 縁は引き伸ばしかタイル。タイルは元の大きさで繰り返し、最後の1枚は切り取り。
- どのサイズでも四隅は拡大されません(100×40・300×80・800×200・420×120で確認)。Chromiumではバイト一致、Firefoxでは半透明の角のピクセルがアルファの丸め1段階ぶん変わることがあります。
- 書き出し:プレビュー、ピクセル・正規化値・Godotのpatch_margin_*・Unityのborder(L・B・R・T)入りのnine-slice.json、SETUP.md。
使い方
- パネルかボタンのPNGをドロップ。
- 提案された境界を採用するか、ドラッグ・入力(矢印で1px、Shiftで10px)。
- 目標サイズで引き伸ばし・タイルをプレビュー。
- ZIPで書き出し。
出力されるファイル
| ファイル | 用途 |
|---|---|
panel.png | 元画像。変更せず、ファイル名を引き継ぎます。 |
previews/100x40.png, 300x80.png, 800x200.png + custom size | 選んだモードと倍率で各プレビューサイズに描いたパネル(任意サイズの既定値は420 × 120)。 |
nine-slice.json | 境界をpixels、normalized(境界 ÷ 幅または高さ)、godot4(patch_margin_*)、unity(L・B・R・T順のborderと順序名)で持ち、モード・倍率・プレビューサイズも記録。 |
SETUP.md | 数値を埋めたGodot 4・Unityの設定手順。エンジン内で実行していないと明記。 |
Godot・Unity・Phaserに境界を入れる
- Godot 4:
NinePatchRectを追加し、TextureにPNGを、patch_margin_left・patch_margin_right・patch_margin_top・patch_margin_bottomにnine-slice.jsonの4つの数値を入れます。 - Godot 4のタイルモード:
axis_stretch_horizontalとaxis_stretch_verticalをTile(またはTile Fit)にします。Button・PanelのテーマならStyleBoxTextureのtexture_margin_*に同じ数値を入れ、軸の伸ばし方も同じにします。 - Unity:テクスチャを選んでMesh TypeをFull RectにしてApplyし、Sprite Editorを開いて緑のハンドルをドラッグするか、L・R・T・Bの欄に
pixelsの値を入力します。 - Unity:Sprite RendererならDraw ModeをSliced(またはTiled、Tile ModeはContinuousかAdaptive)に、UIのImageならImage TypeをSliced(またはTiled)にします。
- Phaser 3.60以降:
this.add.nineslice(x, y, key, frame, width, height, leftWidth, rightWidth, topHeight, bottomHeight)。Phaser 4.1のAPIには、伸ばさずに繰り返すtileX・tileYがあります。 - ピクセルアートではNearestフィルターのまま、元ピクセルの整数倍でサイズを変えて四隅をくっきり保ちます。
結果の確認
- エンジンのノードを300 × 80にして
previews/300x80.pngと比べます。12 × 12の四隅がピクセル単位で一致するはずです。 - L + Rより狭くしてみます。同じサイズでNerulioは"narrow"の警告を出し、PhaserのドキュメントもL + Rを最小幅としています。
- Unityで
Debug.Log(sprite.border)がJSONのunity.borderの数値(左・下・右・上)を出力するはずです。
トラブルシューティング
| 症状 | 考えられる原因 | 確認方法 | 対処 |
|---|---|---|---|
| Unityで四隅が伸びる | Mesh TypeがTight、またはImage・Sprite RendererがまだSimpleで描いている | テクスチャのインポート設定と、Image TypeまたはDraw Mode | Mesh TypeをFull RectにしてApplyし、Image Type SlicedかDraw Mode Slicedに |
| Unityで上下の境界が入れ替わって見える | Vector4の順(左・下・右・上)をL・R・T・Bの欄に入れた、またはその逆 | Sprite Editorの欄とJSONのpixelsを比べる | Sprite Editorにはpixelsを入力し、unity.borderはスクリプトのSprite.borderだけに使う |
| 小さいサイズで四隅がつぶれる | コントロールがL + RまたはT + Bより小さい | Nerulioがそのサイズで"narrow"・"short"の警告を出す | コントロールを大きくするか境界を小さくする |
| 模様のある辺がにじんで見える | 辺を引き伸ばしたため、繰り返し模様がリサンプリングされた | プレビューをタイルに切り替えて比べる | GodotはTile・Tile Fit、UnityはTiled、Phaser 4はtileX・tileY |
| ピクセルアートの角がぼやける | Linearフィルター、または倍率が整数でない | 拡大すると角の段差がやわらかい | Nearestフィルターと整数倍率(エディターの倍率は1〜4) |
| TexturePackerのアトラスでPhaserのNineSliceがおかしい | フレームがトリムされている。PhaserのドキュメントはNineSliceがトリムされたTexturePackerのテクスチャに非対応と記載 | アトラスのJSONでトリムされたフレームを確認 | パネルをトリムなしでパックするか、単独の画像として読み込む |
| 「境界を提案」がはっきりした区間を見つけない | 中央がグラデーションやノイズで、同一の列・行がない | 提案に繰り返す列・行が明確でないと出る | 角の絵が終わる位置にガイドを手で置く |
ほかの方法
| 方法 | こんなときに向いています |
|---|---|
| GodotのNinePatchRectのインスペクターやUnityのSprite Editorで直接設定 | パネルが1〜2枚で、すでにエンジンで作業しているとき。ドラッグしながら実際のエンジンの描画を確認できます。 |
| UIラボのアトラスステージ | 1枚のシートにパネルが多いとき。要素ごとに境界を付け、すべてを1つのui-atlas.jsonにまとめます。 |
出力ファイルと検証方法
「測定確認」は、ダウンロードしたファイルをページ外(Pillow・numpy・独立したパーサー)で開き直して性質を測ったという意味です。ゲームエンジンでの読み込みは試していません。
| 書き出し先 | ファイル | 検証 |
|---|---|---|
| Nine-slice | nine-slice.json · previews · SETUP.md | 測定確認 Pillowリサイズした全プレビューで四隅のブロックは拡大されません。Chromiumではバイト一致、Firefoxでは半透明ピクセルがアルファの丸め1段階ぶん変わることがあります。すき間・重なり0。 |
| Bitmap font | font.png · font.fnt (BMFont text) · font.json | 測定確認 independent .fnt parserテスト内で別に書いたパーサーで.fntを読み戻し、ヘッダーと全グリフ範囲が一致。 |
| Button states | states/*.png · strip · states.json | 測定確認 Pillownormalは元と一致(Chromiumではバイト一致、Firefoxでは半透明ピクセルの色がアルファの丸め1段階以内)。states.jsonの各範囲がストリップから該当状態を正確に切り出します。 |
| Engine import | Godot NinePatchRect · Unity Sprite border · BMFont import | 未検証Godot・Unityでは実行していません。 |
検証の根拠
ナインスライスの四隅が100×40・300×80・800×200・420×120で拡大されず、同一列12本から境界6·6·6·6を提案。ボタン状態:normalは元と一致、disabledはアルファ128のグレー、focusリングも正確。.fntのグリフ記録がJSONと一致。.poの欠落グリフを正確に列挙。白地に黒文字で21:1を測定。画像はブラウザのCanvasを通ります。Chromiumはバイトがそのまま、Firefoxは半透明ピクセルの色を乗算済みの値で1段階に丸めます(Kenneyのボタンで測定:アルファ63で最大4段階)。アルファと不透明ピクセルはそのままです。
制限
- Godot・Unity・Phaserの中での描画は実行していません。数値は各エンジンのドキュメントに合わせたもので、エンジンでの試験結果ではありません。
- エンジンのファイル(
.tres、.meta、Androidの.9.png)は書き出しません。 - 1より大きい整数倍率のタイルモードでは、最後の1枚が元ピクセルの(倍率 − 1) ÷ 倍率ぶんつぶれることがあります。
- カーニングペアなし、フォントは1ページ、MSDFなし。SDF出力はベータです。
- TTFのcmapを解析しないため、欠落グリフのチェックには.fntかラボのフォントが必要です。
- アトラスは1ページで、接している要素は1つとして扱います。
- Godot・Unityでの描画は行っていません。エンジン用の値(patch margin、L・B・R・Tの境界)はドキュメント基準で、エンジンでは未検証です。
バージョンと出典
docs/UI-LAB.mdのためにChromiumで測定しました。書き出したすべてのプレビューの6 × 6の四隅ブロックは100 × 40、300 × 80、800 × 200、420 × 120で元画像とバイト一致し、描画プランは300 × 80、倍率3、8 × 4につぶした場合のいずれもすき間・重なり0でした。縞模様の12 × 12パネルは4pxの周期でタイルされ、提案は同一の列・行12本の区間から6 · 6 · 6 · 6を見つけました。Firefoxでは半透明の角のピクセルがアルファの丸め1段階ぶん変わることがあります。Godot・Unityでの読み込みはUNVERIFIEDです。上のエンジン設定はGodot 4.7、Unity 6、PhaserのAPI公式ドキュメントに基づきます。
参照した公式ドキュメント
よくある質問
Unityはどの順序?
Unityのスクリプトの値Sprite.borderは左・下・右・上の順のVector4で、JSONにはその順で書き、名前も付けます。Sprite Editor自体は同じ数値をL・R・T・Bの欄で表示するので、そこにはピクセル値を入力してください。
GodotやUnityの中で試しましたか?
いいえ。値は両エンジンが文書化しているもので、エンジンでの描画は行っていません。
無料ですか?アカウントは必要ですか?
このページの機能はすべて無料で、アカウントなしで使えます。透かしや制限された書き出しはありません。
スプライトはアップロードされますか?
いいえ。Studioはこのブラウザのタブ内でデコード・パック・書き出しを行います。プロジェクトはブラウザ(IndexedDB)に自動保存され、.nerulioファイルとして保存できます。
Asepriteやエンジンのプラグインは必要ですか?
いいえ。.asepriteファイルはブラウザで読み書きします。エンジン別のバンドルには必要なものが入っています(Godotはインポート設定とシーン、UnityとGodotのタイルセットは小さなエディタースクリプト)。