BooleanSpriteCutterWithTaggedShapes / How to Use FragmentManager

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

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 をロードできず、切断処理が成立しません。

設定手順(自分のプロジェクトに入れる場合)

  1. addons/gdDelaunay/ をプロジェクトに配置します
  2. Project > Project Settings > PluginsgdDelaunay を Enabled にします

サンプルでは

  • res://addons/gdDelaunay/ が含まれています
  • project.godot[editor_plugins] enabledres://addons/gdDelaunay/plugin.cfg が登録済みです

1-2. 破片を自動管理するために FragmentManager を常駐させます(推奨)

目的
切断すると RigidBody2D の破片が多数生成されます。破片は物理演算・衝突判定・描画を持つため、放置すると負荷が上がりやすくなります。FragmentManager を常駐させると、次のような「破片の後始末」を自動化できます。

  • 破片の寿命(TTL)で一定時間後に削除
  • 破片数の上限を超えたら古い順に削除
  • 速度が十分に落ちたら freeze して物理負荷を下げる
    -(任意)画面外に出た破片を削除

設定手順(サンプル同様の運用)

  1. fragment_manager.tscn を用意します(ルート Node2DFragmentManager スクリプトが付いていること)
  2. 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 標準入力での最小構成)

  1. Project > Project Settings > Input Map にアクションを追加します(例:call_cut
  2. キー(例:Space)を割り当てます
  3. 任意のノードに入力監視スクリプトを付け、call_cut() を呼び出します

サンプルでは

  • InputMapcall_cut が登録済みです
  • call_cut に Spaceが割り当て済みです

1-4. 切断対象 Sprite2D を「対象グループ」に入れます

目的
Cutter は毎回 get_tree().get_nodes_in_group(target_sprite_group) で「切断対象候補」を収集します。
したがって、切りたい Sprite2D は必ずこのグループに入っている必要があります。ここが未設定だと、call_cut() を呼んでも「対象がゼロ」になり、見た目上なにも起きません。

また、Cutter は切断対象のスプライトから画像のアルファを読み取り、ベースポリゴン(切断可能領域)を作ります。スプライトにテクスチャが付いていない場合や、アルファしきい値の関係で不透明領域が取れない場合もスキップされます。

設定手順

  1. 切断したい Sprite2D を選択します
  2. Node の Groups に SpriteGroup(または Cutter 側で指定したグループ名)を追加します
  3. Sprite2D.texture が設定されていることを確認します

サンプルでは

  • res://sample.tscnEgggroups=["SpriteGroup"] に入っています

1-5. マスク形状ノードを「マスクグループ」に入れます

目的
Cutter は shape_node_group のグループから「マスク形状」を集め、形状ごとに「その形状と重なった切断対象」を探します。
つまり、マスク形状をどこにも登録していない場合、Cutter は「切断の基準(どこを内側にするか)」を持てないため、切断処理を進められません。

対応形状はスクリプト内で分岐しており、代表的には以下を扱えます。

  • Polygon2D / CollisionPolygon2D
  • CollisionShape2DCircleShape2D / RectangleShape2D / ConvexPolygonShape2D / ConcavePolygonShape2D など)

設定手順

  1. マスクにしたい形状ノードを用意します(例:CollisionShape2D + CircleShape2D
  2. そのノードを Groups に CutterShapeGroup(または Cutter 側で指定したグループ名)として追加します
  3. 切断したいスプライトと重なる位置に配置します
  • 位置関係が合っていないと「AABB が交差しない」扱いで処理されません

サンプルでは

  • res://spritecutter.tscnCollisionShape2D2groups=["CutterShapeGroup"]
  • 形状:CircleShape2Dradius=135.004
  • マスク形状は BooleanSpriteCutterWithTaggedShapes の子として配置され、シーン内で切断対象に重なる位置関係になっています

1-6. Cutter をシーンに配置します

目的
Cutter は以下をすべて「シーン上のノードとして存在していること」を前提に動作します。

  • SceneTree からグループ検索する(切断対象・マスク形状の収集)
  • マスク形状ノードの to_global() などを使い、形状をワールド座標のポリゴンに変換する
  • 切断対象スプライトの to_global() を使い、アルファ由来のローカルポリゴンをワールド座標に変換する
  • 生成した破片を「どのノードの子として」追加する(生成先モードに依存)
  • 必要なら爆心地ノード(inside_explosion_center_node 等)を NodePath で参照する

そのため、単にスクリプトを置くだけでは不十分で、実際にシーン内に Cutter ノードを配置し、切断対象・マスク形状・爆心地などが参照できる状態にする必要があります。

設定手順(サンプルと同じ構成)

  1. Cutter ノード(Node2D)をシーンに置きます
  2. boolean_sprite_cutter_with_tagged_shapes.gd をアタッチします
  3. マスク形状ノード(CutterShapeGroup)を Cutter の子に置きます
  • こうしておくと「Cutter を動かす=マスクも一緒に動く」構成が作りやすくなります
  1. 爆心地を使うなら ForceCenter のような Node2D を Cutter の子に置き、inside_explosion_center_node 等で参照します

サンプルでは

  • res://spritecutter.tscnNode2DBooleanSpriteCutterWithTaggedShapes があり、スクリプトがアタッチ済みです
  • ForceCenter が Cutter の子にあり、inside_explosion_center_node=NodePath("ForceCenter") で参照しています
  • マスク形状 CollisionShape2D2 も Cutter の子で、CutterShapeGroup に登録済みです

2. 実行(どう操作すれば切れるか)

2-1. 切断の実行

処理の流

  1. スペースキーでcall_cut() が呼ばれます
  2. Cutter が SpriteGroup から切断対象候補を収集します
  • Sprite2D は「アルファからベースポリゴンを生成」します
  • 既に切断済み(_already_cut=true)のスプライトはスキップします
  1. Cutter が CutterShapeGroup からマスク形状を収集し、形状ごとに以下を行います
  • AABB 交差 → 矩形ポリゴン交差 → ベースポリゴン交差の順に絞り込み
  • 実際に交差した対象だけを破片化します
  1. 内側領域は Voronoi セルで細分化しつつブーリアン交差で破片生成します
  2. 外側領域はマスクでクリップして破片生成します
  3. 生成された破片は RigidBody2D としてシーンに追加され、インパルス/トルクが与えられます
  4. 元が Sprite2D なら非表示化されます(visible=false_already_cut=true

サンプルでの操作手順

  1. 実行(F5)します
  2. Space(Input Action call_cut)を入力します
  3. Egg が消え、破片が飛散します

2-2. 破片が消える(Manager が有効な場合)

目的
破片は放置すると増え続けるため、サンプルは「一定時間で削除する」設定にして、検証中でも負荷が増えにくいようにしています。これは見た目の演出というより、運用上の安全策です。

サンプルでは

  • FragmentManagerSingleton が Autoload 常駐しています
  • fragment_manager.tscn で TTL が有効です
    • inside_ttl_seconds = 10.0
    • outside_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 はグループ検索で対象を集めるため、対象追加のコストが低い構成です。

手順

  1. 切断したい Sprite2D を選択します
  2. Groups に SpriteGroup を追加します
  3. マスク形状と重なる位置にあることを確認します

サンプルでは

  • Egg のみが SpriteGroup に入っているため、Egg のみ切断されます

5-2. マスク形状を増やす(複数マスクで切る)

目的
複数の形状を同時に置き、「重なった対象だけをそれぞれの形状で切る」ことができます。Cutter は CutterShapeGroup に入っている形状をすべて順に処理します。

手順

  1. 追加したい形状ノード(例:別の CollisionShape2D)を作成します
  2. Groups に CutterShapeGroup を追加します
  3. 切断対象と重なる位置に配置します

サンプルでは

  • CollisionShape2D2(円)だけが CutterShapeGroup に入っています

5-3. 破片をもっと細かくする

目的
割れ方を細かくして「砕けた」印象を強めます。主に内側破片に効きます。

手順

  1. voronoi_seed_count を増やします
  2. 必要に応じて voronoi_seed_density_modevoronoi_seed_density_power で偏りを調整します
  3. 負荷が問題になる場合は simplify_tolerance を増やし、ベースポリゴンの頂点数を減らします

サンプルでは

  • voronoi_seed_count = 20 です

5-4. 破片を早く消す/長く残す

目的
演出時間と負荷のバランスを調整します。サンプルは「検証中に溜まらない」設定(10 秒)です。

手順

  1. fragment_manager.tscn を開きます
  2. inside_ttl_secondsoutside_ttl_seconds を調整します
  3. 残し続けたい場合は *_enable_ttl=false にします(上限管理や freeze の併用推奨)

サンプルでは

  • 内外とも ttl_seconds = 10.0 です

6. トラブルシュート

症状 主な原因 対処
Space を押しても何も起きない call_cut の InputMap が無い/キー割当が違う Input Mapcall_cut を作り、Space を割り当てます
call_cut() は呼んでいるのに切断されない 対象 Sprite2DSpriteGroup に入っていない 対象スプライトの 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() の先頭要素のみを採用します(不透明領域が複数ある素材は意図とずれる可能性があります)

セットアップ

  1. Node2D をシーンに配置し、本スクリプトをアタッチします。
  2. 砕きたい Sprite2D をグループ target_sprite_group(既定: SpriteGroup)に追加します。
  3. マスクとして使うノードをグループ shape_node_group(既定: CutterShapeGroup)に追加します。
  • 対応例:Polygon2D / CollisionPolygon2D / CollisionShape2D(Convex/Concave/Circle/Rectangle)
  1. Inspector で必要なパラメータを設定します(最低限:alpha_thresholdsimplify_tolerancevoronoi_seed_count)。
  2. 切断したいタイミングで 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=FixedVectorinside_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=SpecifiedNodefragment_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 が生成した破片 RigidBody2Dregister_fragment() で登録し、個数上限・生存時間(TTL)・静止判定による freeze・画面外滞留による削除(任意)inside / outside 別設定 で管理するための Node2D スクリプトです。

特徴

  • inside / outside で 別々の管理ポリシー(上限、TTL、freeze、画面外削除)を設定可能です
  • 参照は WeakRef で保持し、ツリーから消えた破片は自動的に参照整理されます
  • freeze 時に任意で 衝突を無効化(collision_layer/mask を 0)できます
  • 画面外判定は ViewportCamera2D から視界矩形を計算して行います(取得できない場合はスキップされます)

前提と必要条件

  • Godot 4 系の 2D ノード構成を前提とします。
  • 管理対象は register_fragment(body) に渡された RigidBody2D です。
  • body には Cutter 側で META_FRAGMENT_TYPE"inside" / "outside")が設定されている必要があります。
  • 管理対象外にしたい破片には META_FRAGMENT_NO_MANAGE=true を付与します。

セットアップ

  1. fragment_manager.tscn のルートノードに本スクリプトをアタッチします。
  2. fragment_manager.tscnProject Settings > Autoload に登録し、/root 配下に常駐させます。
  3. 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削除・画面外削除などでログを出します。
2 Likes

Very good features! I bookmarked this post without hesitation

1 Like