本スクリプトを使用するとスプライト任意のシェイプで分割/細分化し物理ボディを与えて破壊演出を作成することができます。
破片の大きさ、物理特性、分割数、濃度勾配、マテリアルなどを自由に設定することができます。
オプションで分割した破片を更に分割することも可能です。
fragment_manager.gd (16.3 KB)
boolean_sprite_cutter_with_tagged_shapes.gd (59.0 KB)
BooleanSpriteCutterWithTaggedShapesSampleProject.zip (635.2 KB)

※本スクリプトの動作には GDScript Delaunay + Voronoiが必要となります。
※非常に複雑なためサンプルプロジェクトのダウンロードをおすすめします。
使用例、サンプルプロジェクト解説
0. 用語
| 用語 | 意味 |
|---|---|
| Cutter | BooleanSpriteCutterWithTaggedShapes(切断処理本体。call_cut() を持つ) |
| 切断対象 | target_sprite_group に入っている Sprite2D(必要なら再分割対象の破片 RigidBody2D も含む) |
| マスク形状 | shape_node_group に入っている形状ノード(円・矩形・多角形など) |
| 内側破片 | マスクと重なった領域から生成される破片(_fragment_type="inside") |
| 外側破片 | マスク外の残り領域から生成される破片(_fragment_type="outside") |
| Manager | FragmentManager(破片の寿命・上限などを自動管理。Autoload 常駐が基本) |
1. セットアップ(「切断できる状態」を作る)
1-1. Voronoi 分割を使うために gdDelaunay を有効化します
目的
Cutter は、破片の「割り方」を作るために Voronoi 分割を行います。その Voronoi 計算に res://addons/gdDelaunay/Delaunay.gd を使うため、プロジェクトにアドオンが存在し、Plugin が有効になっている必要があります。ここが未設定だと、Cutter の内部で Delaunay をロードできず、切断処理が成立しません。
設定手順(自分のプロジェクトに入れる場合)
addons/gdDelaunay/をプロジェクトに配置しますProject > Project Settings > PluginsでgdDelaunayを Enabled にします
サンプルでは
res://addons/gdDelaunay/が含まれていますproject.godotの[editor_plugins] enabledにres://addons/gdDelaunay/plugin.cfgが登録済みです
1-2. 破片を自動管理するために FragmentManager を常駐させます(推奨)
目的
切断すると RigidBody2D の破片が多数生成されます。破片は物理演算・衝突判定・描画を持つため、放置すると負荷が上がりやすくなります。FragmentManager を常駐させると、次のような「破片の後始末」を自動化できます。
- 破片の寿命(TTL)で一定時間後に削除
- 破片数の上限を超えたら古い順に削除
- 速度が十分に落ちたら freeze して物理負荷を下げる
-(任意)画面外に出た破片を削除
設定手順(サンプル同様の運用)
fragment_manager.tscnを用意します(ルートNode2DにFragmentManagerスクリプトが付いていること)Project > Project Settings > Autoloadに追加します
- Name は Cutter 側が参照する名前と一致させます
- Path は
fragment_manager.tscnの場所を指定します
サンプルでは
- Autoload 名:
FragmentManagerSingleton - Path:
res://fragment_manager.tscn - Cutter 側の既定値
manager_autoload_name="FragmentManagerSingleton"と一致しているため、追加設定なしで自動連携します
1-3. 切断を入力で呼べるように InputMap を設定します
目的
Cutter は「入力を監視するノード」ではなく、「call_cut() が呼ばれたら切断処理を行うノード」です。
そのため、プレイヤー操作やボタンなど、任意のタイミングで call_cut() を呼ぶための入口が必要です。Godot 標準で最も扱いやすい入口が InputMap(Input Action)です。
設定手順(Godot 標準入力での最小構成)
Project > Project Settings > Input Mapにアクションを追加します(例:call_cut)- キー(例:Space)を割り当てます
- 任意のノードに入力監視スクリプトを付け、
call_cut()を呼び出します
サンプルでは
InputMapにcall_cutが登録済みですcall_cutに Spaceが割り当て済みです
1-4. 切断対象 Sprite2D を「対象グループ」に入れます
目的
Cutter は毎回 get_tree().get_nodes_in_group(target_sprite_group) で「切断対象候補」を収集します。
したがって、切りたい Sprite2D は必ずこのグループに入っている必要があります。ここが未設定だと、call_cut() を呼んでも「対象がゼロ」になり、見た目上なにも起きません。
また、Cutter は切断対象のスプライトから画像のアルファを読み取り、ベースポリゴン(切断可能領域)を作ります。スプライトにテクスチャが付いていない場合や、アルファしきい値の関係で不透明領域が取れない場合もスキップされます。
設定手順
- 切断したい
Sprite2Dを選択します - Node の Groups に
SpriteGroup(または Cutter 側で指定したグループ名)を追加します Sprite2D.textureが設定されていることを確認します
サンプルでは
res://sample.tscnのEggがgroups=["SpriteGroup"]に入っています
1-5. マスク形状ノードを「マスクグループ」に入れます
目的
Cutter は shape_node_group のグループから「マスク形状」を集め、形状ごとに「その形状と重なった切断対象」を探します。
つまり、マスク形状をどこにも登録していない場合、Cutter は「切断の基準(どこを内側にするか)」を持てないため、切断処理を進められません。
対応形状はスクリプト内で分岐しており、代表的には以下を扱えます。
Polygon2D/CollisionPolygon2DCollisionShape2D(CircleShape2D/RectangleShape2D/ConvexPolygonShape2D/ConcavePolygonShape2Dなど)
設定手順
- マスクにしたい形状ノードを用意します(例:
CollisionShape2D+CircleShape2D) - そのノードを Groups に
CutterShapeGroup(または Cutter 側で指定したグループ名)として追加します - 切断したいスプライトと重なる位置に配置します
- 位置関係が合っていないと「AABB が交差しない」扱いで処理されません
サンプルでは
res://spritecutter.tscnのCollisionShape2D2がgroups=["CutterShapeGroup"]- 形状:
CircleShape2D、radius=135.004 - マスク形状は
BooleanSpriteCutterWithTaggedShapesの子として配置され、シーン内で切断対象に重なる位置関係になっています
1-6. Cutter をシーンに配置します
目的
Cutter は以下をすべて「シーン上のノードとして存在していること」を前提に動作します。
- SceneTree からグループ検索する(切断対象・マスク形状の収集)
- マスク形状ノードの
to_global()などを使い、形状をワールド座標のポリゴンに変換する - 切断対象スプライトの
to_global()を使い、アルファ由来のローカルポリゴンをワールド座標に変換する - 生成した破片を「どのノードの子として」追加する(生成先モードに依存)
- 必要なら爆心地ノード(
inside_explosion_center_node等)をNodePathで参照する
そのため、単にスクリプトを置くだけでは不十分で、実際にシーン内に Cutter ノードを配置し、切断対象・マスク形状・爆心地などが参照できる状態にする必要があります。
設定手順(サンプルと同じ構成)
- Cutter ノード(
Node2D)をシーンに置きます boolean_sprite_cutter_with_tagged_shapes.gdをアタッチします- マスク形状ノード(
CutterShapeGroup)を Cutter の子に置きます
- こうしておくと「Cutter を動かす=マスクも一緒に動く」構成が作りやすくなります
- 爆心地を使うなら
ForceCenterのようなNode2Dを Cutter の子に置き、inside_explosion_center_node等で参照します
サンプルでは
res://spritecutter.tscnにNode2DのBooleanSpriteCutterWithTaggedShapesがあり、スクリプトがアタッチ済みですForceCenterが Cutter の子にあり、inside_explosion_center_node=NodePath("ForceCenter")で参照しています- マスク形状
CollisionShape2D2も Cutter の子で、CutterShapeGroupに登録済みです
2. 実行(どう操作すれば切れるか)
2-1. 切断の実行
処理の流
- スペースキーで
call_cut()が呼ばれます - Cutter が
SpriteGroupから切断対象候補を収集します
Sprite2Dは「アルファからベースポリゴンを生成」します- 既に切断済み(
_already_cut=true)のスプライトはスキップします
- Cutter が
CutterShapeGroupからマスク形状を収集し、形状ごとに以下を行います
- AABB 交差 → 矩形ポリゴン交差 → ベースポリゴン交差の順に絞り込み
- 実際に交差した対象だけを破片化します
- 内側領域は Voronoi セルで細分化しつつブーリアン交差で破片生成します
- 外側領域はマスクでクリップして破片生成します
- 生成された破片は
RigidBody2Dとしてシーンに追加され、インパルス/トルクが与えられます - 元が
Sprite2Dなら非表示化されます(visible=false、_already_cut=true)
サンプルでの操作手順
- 実行(F5)します
- Space(Input Action
call_cut)を入力します Eggが消え、破片が飛散します
2-2. 破片が消える(Manager が有効な場合)
目的
破片は放置すると増え続けるため、サンプルは「一定時間で削除する」設定にして、検証中でも負荷が増えにくいようにしています。これは見た目の演出というより、運用上の安全策です。
サンプルでは
FragmentManagerSingletonが Autoload 常駐していますfragment_manager.tscnで TTL が有効ですinside_ttl_seconds = 10.0outside_ttl_seconds = 10.0
- そのため、破片は生成から約 10 秒で削除されます
3. Cutter の設定(サンプル値)
3-1. 「どれを切るか/どの形状で切るか」
| 項目 | 目的(何に効くか) | サンプル値(spritecutter.tscn) |
|---|---|---|
target_sprite_group |
切断対象の収集元。ここに入っていないスプライトは一切処理されません | 既定値("SpriteGroup") |
shape_node_group |
マスク形状の収集元。ここが空だと内外の判定ができず処理されません | 既定値("CutterShapeGroup") |
補足(切断されないときの典型原因)
- 対象が
SpriteGroupに入っていない - 形状が
CutterShapeGroupに入っていない - 対象スプライトにテクスチャがない
- マスクと対象がワールド座標で重なっていない(AABB 交差しない)
3-2. 破片の細かさ(Voronoi)
| 項目 | 目的(何に効くか) | サンプル値(spritecutter.tscn) |
|---|---|---|
voronoi_seed_count |
Voronoi のシード数。増やすほどセルが増え、内側破片が細かくなりやすい | 20 |
voronoi_seed_density_mode |
シードの偏り方。中心寄りに密度を上げると「中心が細かい割れ方」になりやすい | 1(TowardMaskCenter) |
補足(負荷と見た目の関係)
voronoi_seed_countを上げるほど、ポリゴン交差計算が増え、負荷が上がりやすくなります- 「どこを細かく割るか」を寄せたい場合は密度モードを使い、単純に個数を上げすぎない方が調整しやすいです
3-3. 飛散方向(内側・外側)
| 項目 | 目的(何に効くか) | サンプル値(spritecutter.tscn) |
|---|---|---|
inside_force_base_strength |
内側破片の飛散の強さ(インパルスの基礎) | 1300.0 |
inside_force_direction_mode |
内側の方向決定(固定ベクトル/爆心地から放射) | 1(ExplosionFromPoint) |
inside_explosion_center_node |
内側の爆心地(NodePath) |
NodePath("ForceCenter") |
outside_force_direction_mode |
外側の方向決定 | 1(ExplosionFromPoint) |
サンプルの爆心地
ForceCenterは Cutter の子ノードですForceCenter.position = (0, 134)- 爆発方向は「破片中心 → 爆心地」ではなく「爆心地 → 破片中心」方向(外向き)になるため、中心から飛び散る見た目になります
3-4. 見た目(エッジ線)
| 項目 | 目的(何に効くか) | サンプル値(spritecutter.tscn) |
|---|---|---|
draw_edge_line |
破片ポリゴンの輪郭を Line2D で描画し、割れ目を視認しやすくする |
false |
補足
- エッジ線は破片ごとに
Line2Dが増えるため、破片数が多いと描画コストが上がりやすくなります - サンプルでは負荷と見た目の簡潔さを優先し、無効になっています
4. FragmentManager の設定(サンプル値)
4-1. 寿命(TTL)
| 項目 | 目的(何に効くか) | サンプル値(fragment_manager.tscn) |
|---|---|---|
inside_enable_ttl / inside_ttl_seconds |
内側破片を一定時間後に削除し、破片が残り続けないようにする | true / 10.0 |
outside_enable_ttl / outside_ttl_seconds |
外側破片を一定時間後に削除する | true / 10.0 |
補足
- TTL は「物理が止まったかどうか」ではなく「生成からの経過時間」で判定されます
- 演出上「割れてしばらく残したい」場合は秒数を増やします
- 「残し続けたい」場合は
*_enable_ttl=falseにしますが、上限管理や freeze 等と組み合わせないと負荷が増えやすくなります
4-2. 静止時 freeze(サンプルは無効)
| 項目 | 目的(何に効くか) | サンプル値(fragment_manager.tscn) |
|---|---|---|
inside_enable_freeze_on_settled |
内側破片が十分に静止したら freeze して物理更新を抑える | false |
outside_enable_freeze_on_settled |
外側破片も同様 | false |
inside_disable_collision_when_frozen |
freeze 後に衝突レイヤー/マスクを 0 にして衝突計算も抑える | false |
outside_disable_collision_when_frozen |
外側も同様 | false |
補足(freeze を有効にする場面)
- 破片が「床に落ちて止まる演出」をしたいが、止まった後の物理更新を減らしたい場合に使います
- freeze すると、後から外力を与えない限り動きません(演出仕様として問題ないかを前提に有効化します)
5. 変更手順(よくある用途)
5-1. 切断対象を増やす
目的
同じ Cutter で複数のスプライトを切断できるようにします。Cutter はグループ検索で対象を集めるため、対象追加のコストが低い構成です。
手順
- 切断したい
Sprite2Dを選択します - Groups に
SpriteGroupを追加します - マスク形状と重なる位置にあることを確認します
サンプルでは
EggのみがSpriteGroupに入っているため、Eggのみ切断されます
5-2. マスク形状を増やす(複数マスクで切る)
目的
複数の形状を同時に置き、「重なった対象だけをそれぞれの形状で切る」ことができます。Cutter は CutterShapeGroup に入っている形状をすべて順に処理します。
手順
- 追加したい形状ノード(例:別の
CollisionShape2D)を作成します - Groups に
CutterShapeGroupを追加します - 切断対象と重なる位置に配置します
サンプルでは
CollisionShape2D2(円)だけがCutterShapeGroupに入っています
5-3. 破片をもっと細かくする
目的
割れ方を細かくして「砕けた」印象を強めます。主に内側破片に効きます。
手順
voronoi_seed_countを増やします- 必要に応じて
voronoi_seed_density_modeとvoronoi_seed_density_powerで偏りを調整します - 負荷が問題になる場合は
simplify_toleranceを増やし、ベースポリゴンの頂点数を減らします
サンプルでは
voronoi_seed_count = 20です
5-4. 破片を早く消す/長く残す
目的
演出時間と負荷のバランスを調整します。サンプルは「検証中に溜まらない」設定(10 秒)です。
手順
fragment_manager.tscnを開きますinside_ttl_secondsとoutside_ttl_secondsを調整します- 残し続けたい場合は
*_enable_ttl=falseにします(上限管理や freeze の併用推奨)
サンプルでは
- 内外とも
ttl_seconds = 10.0です
6. トラブルシュート
| 症状 | 主な原因 | 対処 |
|---|---|---|
| Space を押しても何も起きない | call_cut の InputMap が無い/キー割当が違う |
Input Map に call_cut を作り、Space を割り当てます |
call_cut() は呼んでいるのに切断されない |
対象 Sprite2D が SpriteGroup に入っていない |
対象スプライトの Groups に SpriteGroup を追加します |
call_cut() は呼んでいるのに切断されない |
マスク形状が CutterShapeGroup に入っていない |
形状ノードの Groups に CutterShapeGroup を追加します |
| 切断されない/たまにしか切断されない | マスクと対象が重なっていない(AABB 交差しない) | 位置・スケール・回転を見直し、確実に重なるようにします |
| 破片が増え続ける | FragmentManager が常駐していない/Autoload 名不一致 |
Autoload に FragmentManagerSingleton="*res://fragment_manager.tscn" を設定します |
| 破片が重い | voronoi_seed_count が大きい/エッジ線が有効/破片が残りすぎ |
voronoi_seed_count を下げ、draw_edge_line を無効化し、TTL を短くします |
| 破片がすぐ消える | TTL が短い | inside_ttl_seconds / outside_ttl_seconds を増やします(サンプルは 10 秒) |
BooleanSpriteCutterWithTaggedShapes概要
BooleanSpriteCutterWithTaggedShapes は、指定グループ内の Sprite2D(および再分割を許可した破片)を対象に、別グループの「マスク形状ノード」を使って交差領域を切り出し、Voronoi 分割+ブーリアン演算で破片化し、RigidBody2D 破片を生成する Node2D スクリプトです。
破片は「マスク内(inside)」と「マスク外(outside)」に分類され、それぞれで力・物理・マテリアル等を個別に設定できます。
特徴
- グループ指定で対象スプライトを一括処理(複数同時に切断)
- マスク形状を別グループから収集(複数マスクの順次適用)
- inside / outside で 力(方向/強さ/トルク) を別設定
- 破片の物理設定を Manual / Sprite継承 / Shape継承 / 指定ノード継承 で切替可能
- 破片の生成先を Self / 指定ノード / owner親 / owner子 / Manager から選択可能
- 再分割(リカット)対応(inside/outside それぞれ許可フラグあり)
- エッジライン(
Line2D)描画、マテリアル継承/上書きに対応
前提と必要条件
| 項目 | 内容 |
|---|---|
| 必須アドオン | res://addons/gdDelaunay/Delaunay.gd が存在すること(preload されます) |
| 対象 | target_sprite_group に属する Sprite2D(texture 必須)/再分割対象の破片 RigidBody2D |
| マスク | shape_node_group に属する形状ノード(後述の対応型) |
| 形状の交差 | マスク AABB と対象 AABB が交差し、かつポリゴン交差があるときに切断されます |
| 注意 | スプライトのベースポリゴンは opaque_to_polygons() の先頭要素のみを採用します(不透明領域が複数ある素材は意図とずれる可能性があります) |
セットアップ
Node2Dをシーンに配置し、本スクリプトをアタッチします。- 砕きたい
Sprite2Dをグループtarget_sprite_group(既定:SpriteGroup)に追加します。 - マスクとして使うノードをグループ
shape_node_group(既定:CutterShapeGroup)に追加します。
- 対応例:
Polygon2D/CollisionPolygon2D/CollisionShape2D(Convex/Concave/Circle/Rectangle)
- Inspector で必要なパラメータを設定します(最低限:
alpha_threshold、simplify_tolerance、voronoi_seed_count)。 - 切断したいタイミングで Cutter ノードの
call_cut()を呼びます。
- 例:入力、ボタン、当たり判定イベント、アニメーションイベント等
生成ノード仕様
| 生成物 | 構成 | メタ/グループ | 備考 |
|---|---|---|---|
| inside 破片 | RigidBody2D(子:Polygon2D + CollisionPolygon2D + 任意で Line2D) |
META_IS_FRAGMENT=true / META_FRAGMENT_TYPE="inside" / META_FRAGMENT_SOURCE_SPRITE=元Sprite / target_sprite_group に追加 |
unfreeze_delay>0 の場合は一時 freeze → タイマー後に解除+力適用 |
| outside 破片 | 同上 | META_FRAGMENT_TYPE="outside" |
outside 用の力・物理・マテリアル設定が適用 |
元 Sprite2D |
非表示化 | META_ALREADY_CUT=true |
同一スプライトの二重切断を防止 |
| 再分割元(破片) | queue_free() |
- | 再分割時、元破片は置き換えられます |
使用例
| 目的(ユースケース) | 設定 | 結果 | 補足 |
|---|---|---|---|
| マスクに触れた部分だけ破片化 | shape_node_group にマスク形状を追加 → call_cut() |
交差した Sprite のみ破片生成 | 複数マスクがあれば順に適用 |
| inside だけ右方向に飛ばす | inside_force_direction_mode=FixedVector、inside_force_fixed_vector=(1,0) |
inside 破片が一定方向に飛ぶ | 強さは inside_force_base_strength |
| 爆心地から放射状に飛ばす | *_force_direction_mode=ExplosionFromPoint、*_explosion_center_node 指定 |
破片中心→爆心方向に飛ぶ | call_cut(force_config) でも爆心地を上書き可能 |
| 大きい破片ほど強く/回る挙動にする | use_area_scaling_for_impulse=true / use_area_scaling_for_torque=true |
面積比で力・トルクがスケール | クランプは area_ratio_min/max |
| 破片をシーン上で整理して生成 | fragment_parent_mode=SpecifiedNode(fragment_parent_node 指定) |
破片が指定ノード配下にまとまる | Manager も選択可 |
| 再分割(追い切り)したい | allow_recutted_inside_fragments=true(必要に応じて outside も) |
次回 call_cut() で破片も対象に含まれる |
破片は target_sprite_group に追加される |
| 砕いた後に周辺当たりを無効化 | disable_related_collisions_on_cut=true |
元周辺のコリジョンを無効化 | 生成破片(META_IS_FRAGMENT)は除外 |
プロパティ一覧
基本
| プロパティ | 型 / 既定値 | 説明(挙動・計算・注意点) |
|---|---|---|
target_sprite_group |
String / "SpriteGroup" |
切断対象の Sprite2D(および許可した破片)を収集するグループ名 |
shape_node_group |
String / "CutterShapeGroup" |
マスクとして使う形状ノードを収集するグループ名 |
alpha_threshold |
float / 0.1 |
BitMap.create_from_image_alpha の不透明判定しきい値(alpha >= threshold が不透明) |
simplify_tolerance |
float / 2.0 |
opaque_to_polygons() の簡略化許容誤差(大きいほど軽いが荒い) |
voronoi_seed_count |
int / 10 |
Voronoi 分割のシード点数(増やすほど破片数増・重い) |
density |
float / 1.0 |
質量係数:mass = area_world * density |
unfreeze_delay |
float / 0.0 |
生成後に freeze 解除する遅延秒数(>0 で一時停止演出) |
circle_approx_segments |
int / 32 |
CircleShape2D を多角形近似する分割数 |
debug_log |
bool / false |
true で処理ログを出力(通常は false 推奨) |
Voronoi シード分布
| プロパティ | 型 / 既定値 | 説明 |
|---|---|---|
voronoi_seed_density_mode |
enum / Uniform |
Uniform / TowardMaskCenter / TowardSpriteCenter / TowardNodeCenter |
voronoi_seed_density_power |
float / 2.0 |
中心付近に寄せる強さ(pow(t, power)) |
voronoi_seed_center_node |
NodePath / 空 |
TowardNodeCenter の中心(Node2D.global_position) |
力設定(内側)
| プロパティ | 型 / 既定値 | 説明 |
|---|---|---|
inside_force_base_strength |
float / 1000.0 |
inside 破片に与える基礎インパルス強さ |
inside_force_strength_jitter_ratio |
float / 0.0 |
強さの揺らぎ(±比率、方向は固定) |
inside_force_direction_mode |
enum / FixedVector |
FixedVector / ExplosionFromPoint |
inside_force_fixed_vector |
Vector2 / (1,0) |
FixedVector の向き(内部で正規化) |
inside_explosion_center_node |
NodePath / 空 |
ExplosionFromPoint の爆心地 Node2D |
inside_torque_impulse |
float / 0.0 |
inside 破片に与えるトルク量 |
力設定(外側)
| プロパティ | 型 / 既定値 | 説明 |
|---|---|---|
outside_force_base_strength |
float / 600.0 |
outside 破片に与える基礎インパルス強さ |
outside_force_strength_jitter_ratio |
float / 0.0 |
強さの揺らぎ(±比率) |
outside_force_direction_mode |
enum / FixedVector |
FixedVector / ExplosionFromPoint |
outside_force_fixed_vector |
Vector2 / (0,-1) |
FixedVector の向き |
outside_explosion_center_node |
NodePath / 空 |
ExplosionFromPoint の爆心地 |
outside_torque_impulse |
float / 0.0 |
outside 破片に与えるトルク量 |
サイズスケーリング
| プロパティ | 型 / 既定値 | 説明 |
|---|---|---|
use_area_scaling_for_impulse |
bool / true |
面積比でインパルスをスケールする |
use_area_scaling_for_torque |
bool / true |
面積比でトルクをスケールする |
area_ratio_min |
float / 0.2 |
面積比の下限クランプ |
area_ratio_max |
float / 3.0 |
面積比の上限クランプ |
impulse_area_exponent |
float / 0.5 |
impulse_scale = pow(area_ratio, exponent) |
torque_area_exponent |
float / 1.0 |
torque_scale = pow(area_ratio, exponent) |
マテリアル設定(共通・内側・外側)
| プロパティ | 型 / 既定値 | 説明 |
|---|---|---|
fragment_inherit_material |
bool / true |
元の material を継承する(共通デフォルト) |
fragment_use_custom_material |
bool / false |
共通のカスタム material を強制適用 |
fragment_custom_material |
Material / null |
共通カスタム material |
inside_fragment_inherit_material |
bool / true |
inside 専用:継承するか |
inside_fragment_use_custom_material |
bool / false |
inside 専用:カスタム使用 |
inside_fragment_custom_material |
Material / null |
inside 専用 material |
outside_fragment_inherit_material |
bool / true |
outside 専用:継承するか |
outside_fragment_use_custom_material |
bool / false |
outside 専用:カスタム使用 |
outside_fragment_custom_material |
Material / null |
outside 専用 material |
エッジライン設定
| プロパティ | 型 / 既定値 | 説明 |
|---|---|---|
draw_edge_line |
bool / true |
Line2D で破片エッジを描画する |
edge_line_width |
float / 2.0 |
線幅 |
edge_line_color_inside |
Color / 白 |
inside の線色 |
edge_line_color_outside |
Color / 白 |
outside の線色 |
再分割設定
| プロパティ | 型 / 既定値 | 説明 |
|---|---|---|
allow_recutted_inside_fragments |
bool / false |
inside 破片を次回ターゲットに含める |
allow_recutted_outside_fragments |
bool / false |
outside 破片を次回ターゲットに含める |
元コリジョン無効化
| プロパティ | 型 / 既定値 | 説明 |
|---|---|---|
disable_related_collisions_on_cut |
bool / false |
元スプライト周辺のコリジョンを走査して無効化(生成破片は除外) |
破片生成先
| プロパティ | 型 / 既定値 | 説明 |
|---|---|---|
fragment_parent_mode |
enum / Self |
Self / SpecifiedNode / OwnerParent / OwnerChild / Manager |
fragment_parent_node |
NodePath / 空 |
SpecifiedNode の生成先 |
| 補足 | - | OwnerChild は再分割(owner が破片)時にフォールバックが入ります |
破片物理設定(内側)
| プロパティ | 型 / 既定値 | 説明 |
|---|---|---|
inside_fragment_physics_mode |
enum / FromSprite |
Manual / FromSprite / FromShape / FromSpecified |
inside_fragment_physics_reference_node |
NodePath / 空 |
FromSpecified の参照起点 |
inside_fragment_gravity_scale_manual |
float / 1.0 |
Manual:重力スケール |
inside_fragment_collision_layer_manual |
int(flags) / 1 |
Manual:Collision Layer |
inside_fragment_collision_mask_manual |
int(flags) / 1 |
Manual:Collision Mask |
inside_fragment_linear_damp_manual |
float / 0.0 |
Manual:Linear Damp |
inside_fragment_angular_damp_manual |
float / 0.0 |
Manual:Angular Damp |
inside_fragment_physics_material_manual |
PhysicsMaterial / null |
Manual:摩擦/反発 |
inside_fragment_lock_rotation_manual |
bool / false |
Manual:回転ロック |
破片物理設定(外側)
| プロパティ | 型 / 既定値 | 説明 |
|---|---|---|
outside_fragment_physics_mode |
enum / FromSprite |
Manual / FromSprite / FromShape / FromSpecified |
outside_fragment_physics_reference_node |
NodePath / 空 |
FromSpecified の参照起点 |
outside_fragment_gravity_scale_manual |
float / 1.0 |
Manual:重力スケール |
outside_fragment_collision_layer_manual |
int(flags) / 1 |
Manual:Collision Layer |
outside_fragment_collision_mask_manual |
int(flags) / 1 |
Manual:Collision Mask |
outside_fragment_linear_damp_manual |
float / 0.0 |
Manual:Linear Damp |
outside_fragment_angular_damp_manual |
float / 0.0 |
Manual:Angular Damp |
outside_fragment_physics_material_manual |
PhysicsMaterial / null |
Manual:摩擦/反発 |
outside_fragment_lock_rotation_manual |
bool / false |
Manual:回転ロック |
マネージャ連携
| プロパティ | 型 / 既定値 | 説明 |
|---|---|---|
manager_mode |
enum / Autoload |
None / Autoload / SpecifiedNode |
manager_autoload_name |
String / "FragmentManagerSingleton" |
Autoload 名(/root/<name> を参照) |
manager_node |
NodePath / 空 |
SpecifiedNode の参照先 |
| 挙動 | - | 破片生成時、解決できた Manager に register_fragment(body) を呼びます(メソッドがある場合のみ) |
実行時上書き(call_cut(force_config))
call_cut() の引数 force_config で、Inspector の力設定を その呼び出し回だけ 上書きできます。
| 対象 | キー | 値の例 |
|---|---|---|
| inside/outside | base_strength |
1400.0 |
| inside/outside | strength_jitter_ratio |
0.15 |
| inside/outside | direction_mode |
FORCE_DIR_FIXED_VECTOR または FORCE_DIR_EXPLOSION |
| inside/outside | fixed_vector |
Vector2(1, 0) |
| inside/outside | explosion_center |
Vector2(100, 200)(ワールド座標) |
| inside/outside | torque_impulse |
3.0 |
FragmentManager 概要
FragmentManager は、Cutter が生成した破片 RigidBody2D を register_fragment() で登録し、個数上限・生存時間(TTL)・静止判定による freeze・画面外滞留による削除(任意) を inside / outside 別設定 で管理するための Node2D スクリプトです。
特徴
- inside / outside で 別々の管理ポリシー(上限、TTL、freeze、画面外削除)を設定可能です
- 参照は
WeakRefで保持し、ツリーから消えた破片は自動的に参照整理されます - freeze 時に任意で 衝突を無効化(collision_layer/mask を 0)できます
- 画面外判定は
ViewportのCamera2Dから視界矩形を計算して行います(取得できない場合はスキップされます)
前提と必要条件
- Godot 4 系の 2D ノード構成を前提とします。
- 管理対象は
register_fragment(body)に渡されたRigidBody2Dです。 bodyには Cutter 側でMETA_FRAGMENT_TYPE("inside"/"outside")が設定されている必要があります。- 管理対象外にしたい破片には
META_FRAGMENT_NO_MANAGE=trueを付与します。
セットアップ
fragment_manager.tscnのルートノードに本スクリプトをアタッチします。fragment_manager.tscnをProject Settings > Autoloadに登録し、/root配下に常駐させます。- Cutter 側で破片生成時に
FragmentManager.register_fragment(body)が呼ばれるようにします。
- Cutter 側に「生成時に
register_fragmentを呼ぶ」実装がある場合、Autoload 名や参照先設定を一致させます。
生成ノード仕様
- 本ノード自体は
Node2Dとして常駐し、内部で以下の 2 リストに破片参照を保持します。_fragments_inside(inside 用)_fragments_outside(outside 用)
register_fragment()により登録された破片RigidBody2Dには、管理用に以下のメタ情報が付与されます。_boolean_fragment(破片フラグ)_fragment_spawn_msec(生成時刻 ms)_fragment_last_active_msec(最終アクティブ時刻 ms)
inside_fragment_group_name/outside_fragment_group_nameが空でない場合、登録時に該当グループへ追加されます。
使用例
| 目的(ユースケース) | 設定 | 結果 | 補足 |
|---|---|---|---|
| 破片が増えすぎないようにする | inside_max_fragments / outside_max_fragments を設定 |
上限超過分が古い順に削除される | 0 以下で上限なし |
| 一定時間で自然消滅させる | *_enable_ttl=true、*_ttl_seconds を設定 |
TTL 経過で削除される | 生成時刻は登録時に記録される |
| 静止したら物理計算を止める | *_enable_freeze_on_settled=true |
低速状態が継続すると freeze される | 任意で衝突も無効化できる |
| 画面外に出た破片を回収する | *_delete_when_offscreen=true |
画面外滞留で削除される | カメラ取得不能時は判定自体が行われない |
| 特定の破片だけ残す | body.set_meta("_fragment_no_manage", true) |
Manager が登録・更新を無視する | 生成直後に付与する運用が安全 |
プロパティ一覧
| プロパティ | 型 / 既定値 | 説明(挙動・計算・注意点) |
|---|---|---|
inside_fragment_group_name |
String / "FragmentGroupInside" |
inside 破片を登録時に追加するグループ名です。空文字の場合は追加しません。 |
inside_max_fragments |
int / 300 |
inside 破片の個数上限です。0 以下の場合は無制限です。超過時は古い順に queue_free() されます。 |
inside_enable_ttl |
bool / true |
inside 破片の TTL 削除を有効化します。 |
inside_ttl_seconds |
float / 8.0 |
inside 破片の生存時間(秒)です。now - spawn_msec がこの秒数以上で削除されます。 |
inside_enable_freeze_on_settled |
bool / true |
inside 破片の静止判定 freeze を有効化します。 |
inside_settled_linear_speed |
float / 15.0 |
線形速度しきい値です。これを超えると「アクティブ」とみなされ、最終アクティブ時刻が更新されます。 |
inside_settled_angular_speed |
float / 1.5 |
角速度しきい値です。これを超えると「アクティブ」とみなされます。 |
inside_settled_grace_seconds |
float / 0.6 |
低速状態がこの秒数以上継続すると freeze を適用します。 |
inside_disable_collision_when_frozen |
bool / true |
freeze 時に collision_layer/mask を 0 に設定します。復帰処理は行われません。 |
inside_delete_when_offscreen |
bool / false |
inside 破片の画面外削除を有効化します。 |
inside_offscreen_grace_seconds |
float / 1.0 |
画面外がこの秒数以上継続すると削除します。画面内に戻ると最終アクティブ時刻を更新します。 |
outside_fragment_group_name |
String / "FragmentGroupOutside" |
outside 破片を登録時に追加するグループ名です。空文字の場合は追加しません。 |
outside_max_fragments |
int / 300 |
outside 破片の個数上限です。0 以下の場合は無制限です。超過時は古い順に queue_free() されます。 |
outside_enable_ttl |
bool / true |
outside 破片の TTL 削除を有効化します。 |
outside_ttl_seconds |
float / 8.0 |
outside 破片の生存時間(秒)です。now - spawn_msec がこの秒数以上で削除されます。 |
outside_enable_freeze_on_settled |
bool / true |
outside 破片の静止判定 freeze を有効化します。 |
outside_settled_linear_speed |
float / 15.0 |
outside 用の線形速度しきい値です。 |
outside_settled_angular_speed |
float / 1.5 |
outside 用の角速度しきい値です。 |
outside_settled_grace_seconds |
float / 0.6 |
outside 用の低速継続猶予(秒)です。 |
outside_disable_collision_when_frozen |
bool / true |
outside の freeze 時に collision_layer/mask を 0 に設定します。復帰処理は行われません。 |
outside_delete_when_offscreen |
bool / false |
outside 破片の画面外削除を有効化します。 |
outside_offscreen_grace_seconds |
float / 1.0 |
outside の画面外継続猶予(秒)です。 |
debug_log |
bool / false |
true の場合、上限削除・TTL削除・画面外削除などでログを出します。 |