BooleanSpriteCutterWithTaggedShapes / How to Use FragmentManager

By using this script, you can split/split sprites into arbitrary shapes, assign physical bodies, and create destruction effects.
You can freely set the size of fragments, physical properties, number of divisions, density gradients, materials, and more.
As an option, you can further divide the split fragments.

fragment_manager.gd (16.3 KB)
boolean_sprite_cutter_with_tagged_shapes.gd (59.0 KB)
BooleanSpriteCutterWithTaggedShapesSampleProject.zip (635.2 KB)

Download
※ This script requires GDScript Delaunay + Voronoi.

※ Due to its complexity, we recommend downloading the sample project.

Usage Examples and Sample Project Explanation

0. Terminology

Term Meaning
Cutter BooleanSpriteCutterWithTaggedShapes (The main cutting logic. Has call_cut())
Cut Target Sprite2D in target_sprite_group (Includes RigidBody2D fragments for re-cutting if needed)
Mask Shape Shape nodes in shape_node_group (Circle, Rectangle, Polygon, etc.)
Inside Fragment Fragments generated from the area overlapping the mask (_fragment_type="inside")
Outside Fragment Fragments generated from the remaining area outside the mask (_fragment_type="outside")
Manager FragmentManager (Automatically manages fragment lifespan, limits, etc. Usually runs as an Autoload)

1. Setup (Creating a “Cuttable State”)

1-1. Enable gdDelaunay to use Voronoi splitting

Purpose
The Cutter performs Voronoi splitting to determine how to “divide” the fragments. It uses res://addons/gdDelaunay/Delaunay.gd for this Voronoi calculation. Therefore, the addon must exist in the project, and the Plugin must be enabled. If this is not configured, the Cutter cannot load Delaunay internally, and the cutting process will fail.

Setup Steps (When adding to your own project)

  1. Place addons/gdDelaunay/ in your project
  2. In Project > Project Settings > Plugins, enable gdDelaunay

In the Sample

  • res://addons/gdDelaunay/ is included
  • res://addons/gdDelaunay/plugin.cfg is already registered in [editor_plugins] enabled in project.godot

1-2. Make FragmentManager run as an Autoload (Recommended) to automatically manage fragments

Purpose
When cutting, many RigidBody2D fragments are generated. Since fragments have physics calculations, collision detection, and rendering, leaving them unmanaged can increase load. Running FragmentManager as an Autoload automates “fragment cleanup” as follows:

  • Delete fragments after a certain time based on their lifespan (TTL)
  • Delete oldest fragments if the fragment count exceeds the limit
  • Freeze fragments when their speed drops sufficiently to reduce physics load
  • (Optional) Delete fragments that move off-screen

Setup Steps (For operation similar to the sample)

  1. Prepare fragment_manager.tscn (Ensure the root Node2D has the FragmentManager script attached)
  2. Add it to Project > Project Settings > Autoload
  • The Name must match the name referenced by the Cutter
  • The Path specifies the location of fragment_manager.tscn

In the Sample

  • Autoload Name: FragmentManagerSingleton
  • Path: res://fragment_manager.tscn
  • Since this matches the default value on the Cutter side manager_autoload_name="FragmentManagerSingleton", no additional configuration is needed for automatic linking.

1-3. Configure InputMap to allow calling cutting via input

Purpose
The Cutter is not a “node that monitors input,” but rather a “node that performs cutting when call_cut() is called.”
Therefore, you need an entry point to call call_cut() at any desired timing, such as player actions or button presses. The most convenient entry point in standard Godot is InputMap (Input Action).

Setup Steps (Minimal configuration for standard Godot input)

  1. Add an action to Project > Project Settings > Input Map (e.g., call_cut)
  2. Assign a key (e.g., Space)
  3. Attach an input monitoring script to any node to call call_cut()

In the Sample

  • call_cut is registered in InputMap
  • Space is assigned to call_cut

1-4. Add the cut target Sprite2D to the “Target Group”

Purpose
The Cutter collects “cut target candidates” every time using get_tree().get_nodes_in_group(target_sprite_group).
Therefore, the Sprite2D you want to cut must definitely be in this group. If this is not set, calling call_cut() will result in “zero targets,” and visually nothing will happen.

Additionally, the Cutter reads the alpha from the sprite of the cut target to create a base polygon (the cuttable area). If the sprite has no texture attached, or if no opaque area can be obtained due to the alpha threshold, it will be skipped.

Setup Steps

  1. Select the Sprite2D you want to cut
  2. Add SpriteGroup (or the group name specified on the Cutter side) to the Node’s Groups
  3. Ensure Sprite2D.texture is set

In the Sample

  • Egg in res://sample.tscn is in groups=["SpriteGroup"]

1-5. Add the mask shape nodes to the “Mask Group”

Purpose
The Cutter collects “mask shapes” from the group in shape_node_group and searches for “cut targets overlapping that shape” for each shape.
In other words, if you do not register any mask shapes, the Cutter cannot have a “criterion for cutting (what counts as inside),” and the cutting process cannot proceed.

The supported shapes are branched within the script, but typically handles:

  • Polygon2D / CollisionPolygon2D
  • CollisionShape2D (CircleShape2D / RectangleShape2D / ConvexPolygonShape2D / ConcavePolygonShape2D, etc.)

Setup Steps

  1. Prepare the shape node you want to use as a mask (e.g., CollisionShape2D + CircleShape2D)
  2. Add that node to Groups as CutterShapeGroup (or the group name specified on the Cutter side)
  3. Place it so it overlaps with the sprite you want to cut
  • If the positional relationship is incorrect, it will be treated as “AABBs do not intersect” and processing will not occur.

In the Sample

  • CollisionShape2D2 in res://spritecutter.tscn is in groups=["CutterShapeGroup"]
  • Shape: CircleShape2D, radius=135.004
  • The mask shape is placed as a child of BooleanSpriteCutterWithTaggedShapes and is positioned to overlap with the cut target in the scene.

1-6. Place the Cutter in the scene

Purpose
The Cutter operates on the premise that the following all “exist as nodes in the scene”:

  • Search for groups from the SceneTree (collecting cut targets and mask shapes)
  • Use to_global() of mask shape nodes to convert shapes into polygons in world coordinates
  • Use to_global() of cut target sprites to convert alpha-derived local polygons into world coordinates
  • Add generated fragments as children of “which node” (depends on the generation destination mode)
  • If necessary, reference the explosion center node (inside_explosion_center_node, etc.) via NodePath

Therefore, simply placing the script is not enough; you must actually place the Cutter node in the scene and ensure it can reference cut targets, mask shapes, and explosion centers.

Setup Steps (Same configuration as the sample)

  1. Place a Cutter node (Node2D) in the scene
  2. Attach boolean_sprite_cutter_with_tagged_shapes.gd
  3. Place mask shape nodes (CutterShapeGroup) as children of the Cutter
  • This makes it easy to create a configuration where “moving the Cutter = moving the mask together”
  1. If using an explosion center, place a Node2D like ForceCenter as a child of the Cutter and reference it via inside_explosion_center_node, etc.

In the Sample

  • res://spritecutter.tscn has a Node2D BooleanSpriteCutterWithTaggedShapes with the script attached
  • ForceCenter is a child of the Cutter and is referenced via inside_explosion_center_node=NodePath("ForceCenter")
  • The mask shape CollisionShape2D2 is also a child of the Cutter and is registered in CutterShapeGroup

2. Execution (How to operate to cut)

2-1. Executing the cut

Process Flow

  1. Pressing the Space key calls call_cut()
  2. The Cutter collects cut target candidates from SpriteGroup
  • Sprite2D “generates a base polygon from alpha”
  • Skips sprites that have already been cut (_already_cut=true)
  1. The Cutter collects mask shapes from CutterShapeGroup and performs the following for each shape:
  • Narrow down in order: AABB intersection → Rectangle polygon intersection → Base polygon intersection
  • Only targets that actually intersect are fragmented
  1. The inside area is subdivided into Voronoi cells and fragments are generated via Boolean intersection
  2. The outside area is clipped by the mask to generate fragments
  3. The generated fragments are added to the scene as RigidBody2D, and impulse/torque are applied
  4. If the original was Sprite2D, it is hidden (visible=false, _already_cut=true)

Operation Steps in the Sample

  1. Run (F5)
  2. Input Space (Input Action call_cut)
  3. The Egg disappears, and fragments scatter

2-2. Fragments disappearing (When Manager is enabled)

Purpose
If left unmanaged, fragments will continue to increase. The sample is configured to “delete after a certain time” so that the load does not increase even during verification. This is more of an operational safety measure than a visual effect.

In the Sample

  • FragmentManagerSingleton runs as an Autoload
  • TTL is enabled in fragment_manager.tscn
    • inside_ttl_seconds = 10.0
    • outside_ttl_seconds = 10.0
  • Therefore, fragments are deleted approximately 10 seconds after generation

3. Cutter Settings (Sample Values)

3-1. “What to cut / With which shape”

Item Purpose (What it affects) Sample Value (spritecutter.tscn)
target_sprite_group Source for collecting cut targets. Sprites not in this group are not processed at all Default ("SpriteGroup")
shape_node_group Source for collecting mask shapes. If empty, inside/outside determination is impossible, and processing does not occur Default ("CutterShapeGroup")

Supplementary notes (Typical reasons for not cutting)

  • Target is not in SpriteGroup
  • Shape is not in CutterShapeGroup
  • Target sprite has no texture
  • Mask and target do not overlap in world coordinates (AABBs do not intersect)

3-2. Fragment Fineness (Voronoi)

Item Purpose (What it affects) Sample Value (spritecutter.tscn)
voronoi_seed_count Number of Voronoi seeds. Increasing this increases the number of cells, making inside fragments finer 20
voronoi_seed_density_mode Bias of seeds. Increasing density towards the center tends to create “finer cracks in the center” 1 (TowardMaskCenter)

Supplementary notes (Relationship between load and appearance)

  • Increasing voronoi_seed_count increases polygon intersection calculations, making the load heavier
  • If you want to concentrate “where to cut finely,” use the density mode rather than simply increasing the number, which makes adjustment easier

3-3. Scattering Direction (Inside / Outside)

Item Purpose (What it affects) Sample Value (spritecutter.tscn)
inside_force_base_strength Strength of inside fragment scattering (Base impulse) 1300.0
inside_force_direction_mode Direction determination for inside (Fixed vector / Radial from explosion center) 1 (ExplosionFromPoint)
inside_explosion_center_node Inside explosion center (NodePath) NodePath("ForceCenter")
outside_force_direction_mode Direction determination for outside 1 (ExplosionFromPoint)

Sample Explosion Center

  • ForceCenter is a child node of the Cutter
  • ForceCenter.position = (0, 134)
  • The explosion direction is “Explosion Center → Fragment Center” (outward), resulting in a visual effect of scattering from the center

3-4. Appearance (Edge Lines)

Item Purpose (What it affects) Sample Value (spritecutter.tscn)
draw_edge_line Draw the outline of fragment polygons with Line2D to make cracks more visible false

Supplementary notes

  • Edge lines increase Line2D for each fragment, so if there are many fragments, the rendering cost tends to increase
  • In the sample, to prioritize load and visual simplicity, it is disabled

4. FragmentManager Settings (Sample Values)

4-1. Lifespan (TTL)

Item Purpose (What it affects) Sample Value (fragment_manager.tscn)
inside_enable_ttl / inside_ttl_seconds Delete inside fragments after a certain time to prevent them from remaining true / 10.0
outside_enable_ttl / outside_ttl_seconds Delete outside fragments after a certain time true / 10.0

Supplementary notes

  • TTL is judged by “elapsed time since generation,” not by “whether physics has stopped”
  • If you want to keep them for a while after breaking for visual effects, increase the seconds
  • If you want them to remain indefinitely, set *_enable_ttl=false, but be aware that the load may increase unless combined with limit management or freeze

4-2. Freeze when settled (Sample is disabled)

Item Purpose (What it affects) Sample Value (fragment_manager.tscn)
inside_enable_freeze_on_settled Freeze inside fragments when sufficiently settled to suppress physics updates false
outside_enable_freeze_on_settled Same for outside fragments false
inside_disable_collision_when_frozen Set collision layer/mask to 0 after freezing to suppress collision calculations false
outside_disable_collision_when_frozen Same for outside false

Supplementary notes (When to enable freeze)

  • Used when you want a visual effect of fragments “falling to the ground and stopping,” but want to reduce physics updates after they stop
  • Once frozen, they will not move unless an external force is applied later (Enable with the premise that this does not conflict with visual specifications)

5. Modification Steps (Common Use Cases)

5-1. Increase cut targets

Purpose
Enable cutting multiple sprites with the same Cutter. Since the Cutter collects targets via group search, adding targets has low overhead.

Steps

  1. Select the Sprite2D you want to cut
  2. Add SpriteGroup to Groups
  3. Ensure it is positioned to overlap with the mask shape

In the Sample

  • Only Egg is in SpriteGroup, so only Egg is cut

5-2. Increase mask shapes (Cut with multiple masks)

Purpose
You can place multiple shapes simultaneously and “cut only the overlapping targets with each respective shape.” The Cutter processes all shapes in CutterShapeGroup in order.

Steps

  1. Create the shape node you want to add (e.g., another CollisionShape2D)
  2. Add CutterShapeGroup to Groups
  3. Place it so it overlaps with the cut target

In the Sample

  • Only CollisionShape2D2 (Circle) is in CutterShapeGroup

5-3. Make fragments finer

Purpose
Make the cracks finer to strengthen the impression of “shattering.” This mainly affects inside fragments.

Steps

  1. Increase voronoi_seed_count
  2. Adjust bias with voronoi_seed_density_mode and voronoi_seed_density_power as needed
  3. If load becomes an issue, increase simplify_tolerance to reduce the number of vertices in the base polygon

In the Sample

  • voronoi_seed_count = 20

5-4. Delete fragments faster / Keep them longer

Purpose
Balance visual effect duration and load. The sample is set to “not accumulate during verification” (10 seconds).

Steps

  1. Open fragment_manager.tscn
  2. Adjust inside_ttl_seconds and outside_ttl_seconds
  3. If you want them to remain indefinitely, set *_enable_ttl=false (Recommended to use in conjunction with limit management and freeze)

In the Sample

  • Both inside and outside have ttl_seconds = 10.0

6. Troubleshooting

Symptom Main Cause Solution
Nothing happens when pressing Space call_cut Input Map is missing / Key assignment is different Create call_cut in Input Map and assign Space
call_cut() is called but not cutting Target Sprite2D is not in SpriteGroup Add SpriteGroup to the target sprite’s Groups
call_cut() is called but not cutting Mask shape is not in CutterShapeGroup Add CutterShapeGroup to the shape node’s Groups
Not cutting / Rarely cutting Mask and target do not overlap (AABBs do not intersect) Review position, scale, and rotation to ensure they definitely overlap
Fragments keep increasing FragmentManager is not running / Autoload name mismatch Set Autoload as FragmentManagerSingleton="*res://fragment_manager.tscn"
Fragments are heavy voronoi_seed_count is large / Edge lines enabled / Too many fragments remaining Lower voronoi_seed_count, disable draw_edge_line, and shorten TTL
Fragments disappear immediately TTL is too short Increase inside_ttl_seconds / outside_ttl_seconds (Sample is 10 seconds)

BooleanSpriteCutterWithTaggedShapes Overview

BooleanSpriteCutterWithTaggedShapes is a Node2D script that targets Sprite2D (and fragments allowed for re-cutting) in a specified group, uses “mask shape nodes” from another group to cut out the intersection area, fragments them using Voronoi splitting + Boolean operations, and generates RigidBody2D fragments.
Fragments are classified into “inside mask (inside)” and “outside mask (outside),” and force, physics, materials, etc., can be set individually for each.


Features

  • Batch process target sprites via group specification (cut multiple simultaneously)
  • Collect mask shapes from a separate group (sequential application of multiple masks)
  • Set force (direction/strength/torque) separately for inside / outside
  • Switch fragment physics settings between Manual / Sprite Inheritance / Shape Inheritance / Specified Node Inheritance
  • Select fragment generation destination from Self / Specified Node / Owner Parent / Owner Child / Manager
  • Supports re-cutting (recut) (Separate allow flags for inside/outside)
  • Supports edge line (Line2D) drawing and material inheritance/overwriting

Prerequisites and Requirements

Item Content
Required Addon res://addons/gdDelaunay/Delaunay.gd must exist (It is preloaded)
Target Sprite2D belonging to target_sprite_group (Texture required) / Fragment RigidBody2D for re-cutting
Mask Shape nodes belonging to shape_node_group (See supported types below)
Shape Intersection Cutting occurs only when Mask AABB intersects Target AABB AND there is polygon intersection
Note The base polygon of the sprite adopts only the first element of opaque_to_polygons(). (Materials with multiple opaque areas may not match intentions)

Setup

  1. Place a Node2D in the scene and attach this script.
  2. Add the Sprite2D you want to shatter to the group target_sprite_group (Default: SpriteGroup).
  3. Add nodes to be used as masks to the group shape_node_group (Default: CutterShapeGroup).
  • Supported examples: Polygon2D / CollisionPolygon2D / CollisionShape2D(Convex/Concave/Circle/Rectangle)
  1. Set necessary parameters in the Inspector (Minimum: alpha_threshold, simplify_tolerance, voronoi_seed_count).
  2. Call call_cut() on the Cutter node at the desired timing.
  • Examples: Input, button, collision event, animation event, etc.

Generated Node Specifications

Generated Item Configuration Meta/Group Notes
Inside Fragment RigidBody2D (Child: Polygon2D + CollisionPolygon2D + Optional Line2D) META_IS_FRAGMENT=true / META_FRAGMENT_TYPE="inside" / META_FRAGMENT_SOURCE_SPRITE=OriginalSprite / Added to target_sprite_group If unfreeze_delay>0, temporary freeze → Unfreeze after timer + Apply force
Outside Fragment Same as above META_FRAGMENT_TYPE="outside" Outside-specific force, physics, and material settings are applied
Original Sprite2D Hidden META_ALREADY_CUT=true Prevents double cutting of the same sprite
Re-cut Source (Fragment) queue_free() - When re-cutting, the original fragment is replaced

Usage Examples

Purpose (Use Case) Setting Result Notes
Fragment only the part touching the mask Add mask shape to shape_node_groupcall_cut() Only intersecting Sprite generates fragments If there are multiple masks, they are applied sequentially
Fly inside fragments only to the right inside_force_direction_mode=FixedVector, inside_force_fixed_vector=(1,0) Inside fragments fly in a fixed direction Strength is determined by inside_force_base_strength
Fly radially from explosion center *_force_direction_mode=ExplosionFromPoint, specify *_explosion_center_node Fragments fly from fragment center → explosion center Explosion center can be overridden via call_cut(force_config)
Make larger fragments fly stronger/rotate use_area_scaling_for_impulse=true / use_area_scaling_for_torque=true Force and torque scale by area ratio Clamping is done via area_ratio_min/max
Organize and generate fragments on the scene fragment_parent_mode=SpecifiedNode (Specify fragment_parent_node) Fragments are grouped under the specified node Manager can also be selected
Want to re-cut (chase cut) allow_recutted_inside_fragments=true (and outside if needed) Fragments are included in the target for the next call_cut() Fragments are added to target_sprite_group
Disable surrounding collisions after shattering disable_related_collisions_on_cut=true Disable collisions around the original Generated fragments (META_IS_FRAGMENT) are excluded

Property List

Basic

Property Type / Default Description (Behavior, Calculation, Notes)
target_sprite_group String / "SpriteGroup" Group name to collect Sprite2D (and allowed fragments) as cut targets
shape_node_group String / "CutterShapeGroup" Group name to collect shape nodes to be used as masks
alpha_threshold float / 0.1 Opacity judgment threshold for BitMap.create_from_image_alpha (alpha >= threshold is opaque)
simplify_tolerance float / 2.0 Simplification tolerance for opaque_to_polygons() (Larger is lighter but rougher)
voronoi_seed_count int / 10 Number of Voronoi splitting seed points (More fragments, heavier load)
density float / 1.0 Mass coefficient: mass = area_world * density
unfreeze_delay float / 0.0 Delay in seconds to unfreeze after generation (>0 for temporary pause effect)
circle_approx_segments int / 32 Number of divisions to approximate CircleShape2D as a polygon
debug_log bool / false Outputs processing logs if true (False is recommended for normal use)

Voronoi Seed Distribution

Property Type / Default Description
voronoi_seed_density_mode enum / Uniform Uniform / TowardMaskCenter / TowardSpriteCenter / TowardNodeCenter
voronoi_seed_density_power float / 2.0 Strength of bias towards the center (pow(t, power))
voronoi_seed_center_node NodePath / Empty Center for TowardNodeCenter (Node2D.global_position)

Force Settings (Inside)

Property Type / Default Description
inside_force_base_strength float / 1000.0 Base impulse strength applied to inside fragments
inside_force_strength_jitter_ratio float / 0.0 Strength jitter (±ratio, direction is fixed)
inside_force_direction_mode enum / FixedVector FixedVector / ExplosionFromPoint
inside_force_fixed_vector Vector2 / (1,0) Direction for FixedVector (Normalized internally)
inside_explosion_center_node NodePath / Empty Explosion center Node2D for ExplosionFromPoint
inside_torque_impulse float / 0.0 Torque amount applied to inside fragments

Force Settings (Outside)

Property Type / Default Description
outside_force_base_strength float / 600.0 Base impulse strength applied to outside fragments
outside_force_strength_jitter_ratio float / 0.0 Strength jitter (±ratio)
outside_force_direction_mode enum / FixedVector FixedVector / ExplosionFromPoint
outside_force_fixed_vector Vector2 / (0,-1) Direction for FixedVector
outside_explosion_center_node NodePath / Empty Explosion center for ExplosionFromPoint
outside_torque_impulse float / 0.0 Torque amount applied to outside fragments

Size Scaling

Property Type / Default Description
use_area_scaling_for_impulse bool / true Scale impulse by area ratio
use_area_scaling_for_torque bool / true Scale torque by area ratio
area_ratio_min float / 0.2 Lower clamp for area ratio
area_ratio_max float / 3.0 Upper clamp for area ratio
impulse_area_exponent float / 0.5 impulse_scale = pow(area_ratio, exponent)
torque_area_exponent float / 1.0 torque_scale = pow(area_ratio, exponent)

Material Settings (Common / Inside / Outside)

Property Type / Default Description
fragment_inherit_material bool / true Inherit original material (Common default)
fragment_use_custom_material bool / false Force apply common custom material
fragment_custom_material Material / null Common custom material
inside_fragment_inherit_material bool / true Inside only: Inherit or not
inside_fragment_use_custom_material bool / false Inside only: Use custom
inside_fragment_custom_material Material / null Inside only material
outside_fragment_inherit_material bool / true Outside only: Inherit or not
outside_fragment_use_custom_material bool / false Outside only: Use custom
outside_fragment_custom_material Material / null Outside only material

Edge Line Settings

Property Type / Default Description
draw_edge_line bool / true Draw fragment edges with Line2D
edge_line_width float / 2.0 Line width
edge_line_color_inside Color / White Inside line color
edge_line_color_outside Color / White Outside line color

Re-cut Settings

Property Type / Default Description
allow_recutted_inside_fragments bool / false Include inside fragments in the next target
allow_recutted_outside_fragments bool / false Include outside fragments in the next target

Disable Original Collisions

Property Type / Default Description
disable_related_collisions_on_cut bool / false Scan and disable collisions around the original sprite (Excludes generated fragments)

Fragment Generation Destination

Property Type / Default Description
fragment_parent_mode enum / Self Self / SpecifiedNode / OwnerParent / OwnerChild / Manager
fragment_parent_node NodePath / Empty Generation destination for SpecifiedNode
Note - OwnerChild has a fallback when re-cutting (owner is a fragment)

Fragment Physics Settings (Inside)

Property Type / Default Description
inside_fragment_physics_mode enum / FromSprite Manual / FromSprite / FromShape / FromSpecified
inside_fragment_physics_reference_node NodePath / Empty Reference start for FromSpecified
inside_fragment_gravity_scale_manual float / 1.0 Manual: Gravity scale
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: Friction/Bounce
inside_fragment_lock_rotation_manual bool / false Manual: Rotation lock

Fragment Physics Settings (Outside)

Property Type / Default Description
outside_fragment_physics_mode enum / FromSprite Manual / FromSprite / FromShape / FromSpecified
outside_fragment_physics_reference_node NodePath / Empty Reference start for FromSpecified
outside_fragment_gravity_scale_manual float / 1.0 Manual: Gravity scale
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: Friction/Bounce
outside_fragment_lock_rotation_manual bool / false Manual: Rotation lock

Manager Integration

Property Type / Default Description
manager_mode enum / Autoload None / Autoload / SpecifiedNode
manager_autoload_name String / "FragmentManagerSingleton" Autoload name (References /root/<name>)
manager_node NodePath / Empty Reference destination for SpecifiedNode
Behavior - When generating fragments, calls register_fragment(body) on the resolved Manager (if the method exists)

Runtime Override (call_cut(force_config))

You can override the Inspector force settings for that single call via the force_config argument of call_cut().

Target Key Example Value
Inside/Outside base_strength 1400.0
Inside/Outside strength_jitter_ratio 0.15
Inside/Outside direction_mode FORCE_DIR_FIXED_VECTOR or FORCE_DIR_EXPLOSION
Inside/Outside fixed_vector Vector2(1, 0)
Inside/Outside explosion_center Vector2(100, 200) (World coordinates)
Inside/Outside torque_impulse 3.0

FragmentManager Overview

FragmentManager is a Node2D script that registers fragments RigidBody2D generated by the Cutter via register_fragment() and manages maximum count, lifespan (TTL), freeze based on settled state, and deletion for staying off-screen (optional) with separate settings for inside / outside.

Features

  • Separate management policies (limits, TTL, freeze, off-screen deletion) can be set for inside / outside
  • References are held via WeakRef, and references are automatically cleaned up if fragments are removed from the tree
  • Collisions can be disabled (collision_layer/mask set to 0) optionally when freezing
  • Off-screen judgment calculates the view rectangle from the Viewport’s Camera2D (Skipped if not obtainable)

Prerequisites and Requirements

  • Assumes Godot 4 series 2D node structure.
  • The managed objects are RigidBody2D passed to register_fragment(body).
  • body must have META_FRAGMENT_TYPE ("inside" / "outside") set on the Cutter side.
  • Assign META_FRAGMENT_NO_MANAGE=true to fragments you do not want to manage.

Setup

  1. Attach this script to the root node of fragment_manager.tscn.
  2. Register fragment_manager.tscn in Project Settings > Autoload to make it resident under /root.
  3. Ensure FragmentManager.register_fragment(body) is called when generating fragments on the Cutter side.
  • If the Cutter has an implementation to call register_fragment upon generation, match the Autoload name and reference settings.

Generated Node Specifications

  • This node itself resides as a Node2D and internally holds fragment references in the following two lists.
    • _fragments_inside (For inside)
    • _fragments_outside (For outside)
  • Fragments RigidBody2D registered via register_fragment() are assigned the following meta information for management.
    • _boolean_fragment (Fragment flag)
    • _fragment_spawn_msec (Generation time ms)
    • _fragment_last_active_msec (Last active time ms)
  • If inside_fragment_group_name / outside_fragment_group_name is not empty, they are added to the corresponding group upon registration.

Usage Examples

Purpose (Use Case) Setting Result Notes
Prevent fragments from increasing too much Set inside_max_fragments / outside_max_fragments Excess fragments are deleted in order of age Unlimited if 0 or less
Natural disappearance after a certain time Set *_enable_ttl=true, *_ttl_seconds Deleted when TTL expires Generation time is recorded upon registration
Stop physics calculations when settled Set *_enable_freeze_on_settled=true Freezes if low speed state continues Collisions can be disabled optionally
Collect fragments that go off-screen Set *_delete_when_offscreen=true Deleted if staying off-screen Judgment itself is not performed if camera cannot be obtained
Keep only specific fragments body.set_meta("_fragment_no_manage", true) Manager ignores registration and updates Safest to assign immediately after generation

Property List

Property Type / Default Description (Behavior, Calculation, Notes)
inside_fragment_group_name String / "FragmentGroupInside" Group name to add inside fragments upon registration. If empty string, does not add.
inside_max_fragments int / 300 Maximum number of inside fragments. Unlimited if 0 or less. Excess fragments are queue_free() in order of age.
inside_enable_ttl bool / true Enable TTL deletion for inside fragments.
inside_ttl_seconds float / 8.0 Lifespan (seconds) for inside fragments. Deleted if now - spawn_msec exceeds this number of seconds.
inside_enable_freeze_on_settled bool / true Enable settled judgment freeze for inside fragments.
inside_settled_linear_speed float / 15.0 Linear speed threshold. If exceeded, considered “active,” and last active time is updated.
inside_settled_angular_speed float / 1.5 Angular speed threshold. If exceeded, considered “active.”
inside_settled_grace_seconds float / 0.6 Freeze is applied if low speed state continues for this many seconds.
inside_disable_collision_when_frozen bool / true Sets collision_layer/mask to 0 when freezing. No recovery processing is performed.
inside_delete_when_offscreen bool / false Enable off-screen deletion for inside fragments.
inside_offscreen_grace_seconds float / 1.0 Deleted if off-screen continues for this many seconds. Last active time is updated if it returns on-screen.
outside_fragment_group_name String / "FragmentGroupOutside" Group name to add outside fragments upon registration. If empty string, does not add.
outside_max_fragments int / 300 Maximum number of outside fragments. Unlimited if 0 or less. Excess fragments are queue_free() in order of age.
outside_enable_ttl bool / true Enable TTL deletion for outside fragments.
outside_ttl_seconds float / 8.0 Lifespan (seconds) for outside fragments. Deleted if now - spawn_msec exceeds this number of seconds.
outside_enable_freeze_on_settled bool / true Enable settled judgment freeze for outside fragments.
outside_settled_linear_speed float / 15.0 Linear speed threshold for outside.
outside_settled_angular_speed float / 1.5 Angular speed threshold for outside.
outside_settled_grace_seconds float / 0.6 Low speed continuation grace period (seconds) for outside.
outside_disable_collision_when_frozen bool / true Sets collision_layer/mask to 0 when freezing outside. No recovery processing is performed.
outside_delete_when_offscreen bool / false Enable off-screen deletion for outside fragments.
outside_offscreen_grace_seconds float / 1.0 Off-screen continuation grace period (seconds) for outside.
debug_log bool / false If true, outputs logs for limit deletion, TTL deletion, off-screen deletion, etc.
3 Likes

Very good features! I bookmarked this post without hesitation

1 Like