本文へスキップ

ヒットボックス エディター · フレームごとの当たり判定

攻撃のフレームにヒット・ハート・インタラクト・任意のボックスを描き、タグに沿ってコピーし、フレームごとに微調整。同じボックスは全フレームで同じIDを持つので、エンジン側で追跡できます。

ヒットボックス(ダメージを与える範囲)とハートボックス(攻撃を受ける範囲)は、ゲームのコードが判定に使うフレームごとの図形で、画像の一部ではありません。Nerulioでは、フレームごとにhit・hurt・interactや任意の名前の矩形・円・ポリゴンのボックスを描き、1つのボックスを同じIDのままタグ全体にコピーし、フレームごとに微調整できます。すべてのボックスはGodotバンドルのメタデータと汎用JSONに、矩形はAsepriteのスライスにも書き出されます。エンジンのノードやコライダーは生成しないので、Area2Dの形状やUnityのコライダー、Phaserのボディはこのデータから組み立てます。

スプライトシート、連番フレーム、GIF・APNG、.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

ボックスはフレームに属し、エンジンはデータから作る

アクションゲームはアニメーションに合わせてボックスを出し入れします。攻撃のヒットボックスは有効なフレームにだけあり、ハートボックスは毎フレーム体を追います。そのためボックスはスプライトではなくフレームに属し、同じ論理的なボックスはフレームをまたいで1つの身元を持つ必要があります。Nerulioのボックスは、ID・種類・フレームキャンバスのピクセル(原点は左上、yは下向き)での図形を持ち、タグ範囲で描いたりコピーしたりするとIDが保たれるので、コードは剣のボックスをフレームごとに追えます。

エンジンは画像からボックスを読みません。GodotはCollisionShape2DやCollisionPolygon2Dを子に持つArea2Dノードで重なりを検出し、Unityはローカル単位のサイズとオフセットを持つBoxCollider2DなどのCollider2Dコンポーネントを使い、PhaserのArcadeボディはsetSize・setOffset・setCircleで大きさを決め、指定しなければフレームの大きさになります。どれもフレームごとの形状の更新は、コードかアニメーショントラックで自分で行います。書き出しは数値を渡すだけで、そうしたノードやコンポーネントは作りません。

ボックスの座標はフレームキャンバス基準です。オブジェクトに置くにはピボットを引きます。オフセットが −ピボットのGodotのシーンでは、フレーム上 (x, y) のボックスはノード空間の (x − ピボットx, y − ピボットy) にあります。Unityはyが上向きで単位はユニットなので、Pixels Per Unit(Unity書き出しでは100)で割ります。

ヒットボックス
攻撃フレームでダメージを与える範囲。
ハートボックス
体のうち攻撃を受ける範囲。
ボックスID
ボックスをコピーした全フレームで同じなので、コードが1つのボックスを追える。
フレームキャンバスのピクセル
フレーム全体のキャンバスの左上角からの座標。yは下向き。

例:1つのヒットボックスをGodotとUnityに置く

フレームキャンバス48 × 64、ピボット (24, 64)。attackの4〜6フレーム目に x 34、y 30、16 × 12pxのヒットボックス。

Nerulio(キャンバス、y下向き)   x 34、y 30、w 16、h 12
ピボット基準                     左 34 − 24 = 10、上 30 − 64 = −34
Godotのノード空間(y下向き)     矩形 10, −34, 16 × 12、中心 (18, −28)
Unity(y上向き、100px/ユニット)  中心 ((34 + 8 − 24) ÷ 100, (64 − (30 + 6)) ÷ 100) = (0.18, 0.28)
                                 サイズ (0.16, 0.12)
Godotのメタデータ                get_meta("nerulio")["frames"]["attack_004"]["boxes"]
                                 [{"id": …, "type": "hit", "shape": "rect", "x": 34, "y": 30, "w": 16, "h": 12}]

円はcx・cy・r、ポリゴンは点のリストとして、同じピクセル単位で保存されます。攻撃判定ではなく体の衝突形状が欲しい場合は衝突ポリゴン生成を参照してください。

ボックスが入る書き出し

書き出し先書き出しに入るボックスエンジンで作るもの
Godot 4すべてのボックス(矩形・円・ポリゴン)をID・種類つきでフレームごとにSpriteFramesの metadata/nerulio へCollisionShape2DかCollisionPolygon2Dを子に持つArea2Dを、スクリプトでフレームごとに動かす(メタデータはGodot 4.7.2で読み戻し確認)
汎用JSONフレームごとの全ボックス、ピボット、衝突ポリゴンどのエンジンでも frames[key].boxes を読む
.aseprite、Aseprite JSON矩形のみ:ボックスの種類と順番ごとに1スライス、ボックスが変わるフレームにキー。円とポリゴンは除外Asepriteでスライスとして見える(Aseprite 1.3.18で確認)。JSONを読む側は meta.slices
Unity 6なし。書き出しの注記に出る汎用JSONを読む自作スクリプトでコライダーを作る
Phaser、PixiJS、LÖVE、Spine、Starling、Defold、GameMaker、CSSなしアトラスの隣に汎用JSONも読み込む

できること

  • 整数ピクセルにスナップする矩形(B)・円(C)・ポリゴン(Q)ボックス。
  • ヒット・ハート・インタラクト・任意名の種類と、種類ごとの色。
  • 範囲:1フレーム、選択、タグ全体、全フレーム。Alt+Bで次のフレームへコピー。
  • フレームキャンバス外のボックスも印を付けて保持し、Asepriteスライス・Godotバンドル・汎用JSONへ書き出し。

使い方

  1. スプライトを入れて読み込みを適用。
  2. ボックスの種類と範囲を選び、フレーム上でドラッグ。
  3. アニメーションを送りながらフレームごとに調整(矢印1px、Shiftで10px)。
  4. 書き出すとボックスがフレームと一緒に渡ります。

結果の確認

  • , と . で攻撃をコマ送りし、フレームごとのボックスを見ます。フレームキャンバスの外にはみ出したボックスも保持され、印が付きます。
  • Godotに書き出したら、print($Hero.sprite_frames.get_meta("nerulio")["frames"].keys()) でフレームキーを確認し、各項目の boxes にボックスがあるか見ます。
  • .asepriteに書き出したらAsepriteで開きます。矩形ボックスの種類ごとにスライスがあり、ボックスが動くフレームでキーが変わります。

トラブルシューティング

症状考えられる原因確認方法対処
Asepriteで円やポリゴンのボックスがないAsepriteのスライスは矩形なので、.aseprite書き出しはほかの図形を飛ばし、その名前を知らせる書き出しメッセージに飛ばしたボックスが出るAsepriteまで届けたいボックスは矩形で描くか、円とポリゴンは汎用JSONから読む
エンジンでボックスの位置がずれるボックスの座標はピボットではなくフレームキャンバスの左上角から始まる上の例とボックスを1つ比べるピボットを引く。Unityではさらにyを反転しPixels Per Unitで割る
あってはいけないフレームにボックスが出る範囲をタグか全フレームにして描いた、またはコピーしたコマ送りすると同じIDが各フレームにあるそのフレームで削除するか、範囲を「このフレーム」にして描き直す
Unityに取り込んだ結果にボックスがないUnity書き出しはスプライト矩形・ピボット・クリップだけを書く書き出しの注記:ヒットボックスを入れるUnityのスプライト項目がない汎用JSONも書き出し、そこからコライダーを作る

ほかの方法

方法こんなときに向いています
エンジン側で形状を描く(GodotのCollisionShape2D、UnityのBoxCollider2D、PhaserのボディのsetSize・setOffset)フレームごとに変わらないボックスが1〜2個のとき。
Asepriteのスライス絵の横で矩形のボックスを描くとき。Nerulioは名前付きスライス(hit、hurt …)をボックスとして読み込み、書き戻します。

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

「検証済み」は、実際の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は完全一致。

検証の根拠

GIFデコーダー:実在のGIF 29本で408/408フレームがPillowと一致、APNG 16本で132/132。.aseprite:コーパス231ファイルを読み込み・書き直し、Aseprite 1.3.18で開いてタグ・長さ・ピクセルが231/231一致。書き出し:実在のCC0アセットで実際のエンジンを49回実行し47回合格。失敗2回はPhaser 3.90のトリムXMLの不具合で、Phaser 3プリセットで回避できます。

制限

  • エンジンのノード・コライダー・物理ボディは生成しません。書き出しに入るのはデータだけです。
  • Aseprite形式に入るのは矩形のボックスだけです。
  • ボックスの座標はフレームキャンバス上の整数ピクセルです。
  • グリッド・島の推定は信頼度つきのプレビューで、「適用」を押すまで何も切りません。すべての選択に代替案があり、ワンクリックで切り替えられます。
  • レイヤーが正確に合成できない.asepriteファイル(グループの不透明度など)は統合して読み込み、理由を読み込みパネルに表示します。
  • 読み込んだアトラス内の回転フレームは回転したままで、その書き出しは未検証です。
  • 画像は一辺32,768px(2億6,800万ピクセル)まで。ブラウザのメモリにも依存します。

バージョンと出典

Godotバンドルのボックスは Godot 4.7.2 が、矩形のスライスは Aseprite 1.3.18 が読み戻しました(フレームキャンバスからはみ出したボックスを含む)。ノードとコンポーネントの名前は Godot 4.7、Unity 6、Phaser のドキュメントに従います。

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

よくある質問

攻撃全体にひとつのボックスを描けますか?

はい。範囲をタグにすると、1回のドラッグでそのタグの全フレームに同じボックス(同じID)が入り、移動も1回の取り消し単位でまとめて行われます。

どの形式にボックスが入りますか?

すべてのボックスはGodotバンドルのメタデータと汎用JSONに入ります。.asepriteとAseprite JSONには矩形だけがスライスとして入り、Unityにはボックスは入りません。Godotバンドルのボックスは Godot 4.7.2 で読み込みを確認しました。

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

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

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

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

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

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