本文へスキップ

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で、エンジン内での描画は実行していません。

UIパネル・ボタン・グリフシート・UIシート(PNG)をドロップ
UIラボを開く
ブラウザ内で処理し、ファイルはアップロードされません。
UIラボ:ナインスライスのガイドと複数サイズのプレビューがあるCC0のUIパネル
CC0アセット(Kenney)を開いた実際のUIラボ画面です。
出力
  • 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。

使い方

  1. パネルかボタンのPNGをドロップ。
  2. 提案された境界を採用するか、ドラッグ・入力(矢印で1px、Shiftで10px)。
  3. 目標サイズで引き伸ばし・タイルをプレビュー。
  4. 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に境界を入れる

  1. Godot 4:NinePatchRectを追加し、TextureにPNGを、patch_margin_left・patch_margin_right・patch_margin_top・patch_margin_bottomにnine-slice.jsonの4つの数値を入れます。
  2. Godot 4のタイルモード:axis_stretch_horizontalとaxis_stretch_verticalをTile(またはTile Fit)にします。Button・PanelのテーマならStyleBoxTextureのtexture_margin_*に同じ数値を入れ、軸の伸ばし方も同じにします。
  3. Unity:テクスチャを選んでMesh TypeをFull RectにしてApplyし、Sprite Editorを開いて緑のハンドルをドラッグするか、L・R・T・Bの欄にpixelsの値を入力します。
  4. Unity:Sprite RendererならDraw ModeをSliced(またはTiled、Tile ModeはContinuousかAdaptive)に、UIのImageならImage TypeをSliced(またはTiled)にします。
  5. Phaser 3.60以降:this.add.nineslice(x, y, key, frame, width, height, leftWidth, rightWidth, topHeight, bottomHeight)。Phaser 4.1のAPIには、伸ばさずに繰り返すtileX・tileYがあります。
  6. ピクセルアートでは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 ModeMesh 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-slicenine-slice.json · previews · SETUP.md測定確認 Pillowリサイズした全プレビューで四隅のブロックは拡大されません。Chromiumではバイト一致、Firefoxでは半透明ピクセルがアルファの丸め1段階ぶん変わることがあります。すき間・重なり0。
Bitmap fontfont.png · font.fnt (BMFont text) · font.json測定確認 independent .fnt parserテスト内で別に書いたパーサーで.fntを読み戻し、ヘッダーと全グリフ範囲が一致。
Button statesstates/*.png · strip · states.json測定確認 Pillownormalは元と一致(Chromiumではバイト一致、Firefoxでは半透明ピクセルの色がアルファの丸め1段階以内)。states.jsonの各範囲がストリップから該当状態を正確に切り出します。
Engine importGodot 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のタイルセットは小さなエディタースクリプト)。