SoftBody2D
Inherits: Polygon2D
A 2D softbody generated from a texture: one RigidBody2D per region with a CollisionShape2D, Joint2Ds between neighbours, and a Skeleton2D whose bones deform the texture. Everything below is grouped the way the inspector groups it.
Properties
General
| Property | Type | Default | Description |
|---|---|---|---|
draw_regions | bool | false | Draw the generated regions instead of building the softbody, to see how it will be split. |
vertex_interval | float | 30 | Distance between regions, in pixels. Changing it also resets radius to a value derived from it. |
bake_scale | Vector2 | (1, 1) | Scale baked into the generated geometry. Use it instead of the node's scale, which physics does not support; scaling the node in the editor folds into it. A larger softbody gets more particles of the same size. |
Region
| Property | Type | Default | Description |
|---|---|---|---|
pattern_type | "hexagon" | "rectangle" | "hexagon" | Layout of the region grid. |
exclude_texture | Texture2D | Texture whose outline is cut out of the softbody, making a hole. | |
texture_epsilon | float | 1 | Outline simplification; lower keeps more points. |
min_alpha | float | 0.05 | Alpha above which a pixel counts as part of the texture. |
margin_pixels | int | 0 | Grows (positive) or shrinks (negative) the outline. |
polygon_offset | Vector2 | (0, 0) | Shifts the region grid over the texture. |
min_area | float | 0.2 | Regions clipped below this share of a full region are merged into a neighbour. Around 0.08 keeps small corners as their own body. |
Joint
| Property | Type | Default | Description |
|---|---|---|---|
joint_type | "pin" | "spring" | "pin" | PinJoint2D or DampedSpringJoint2D between neighbours. |
bias | float | 0 | Joint2D.bias of every joint. |
disable_collision | bool | true | Jointed bodies do not collide with each other. |
joint_reach | int | 2 | How far joints reach, in hops. 1 joins neighbours only; 2 also joins bodies two hops away, which holds the overall shape; 3 one hop further. See Joints. |
| yield_strain | float | 0 | Squeeze past which a joint takes a permanent set (clay); stretching always springs back. 0 is elastic. Interior joints need interior_strength times as much. |
| yield_limit | float | 0.3 | Most permanent squeeze a joint may accumulate; past it, it stops yielding. |
Joint / Break
| Property | Type | Default | Description |
|---|---|---|---|
break_mode | BreakMode | DISTANCE | Which criterion breaks joints. The other modes' settings are hidden. |
break_distance_ratio | float | 0 | Distance mode: joints break once stretched this many times their generated distance. 0 disables breaking. |
break_force | float | 0 | Force mode: joints break once the force holding them exceeds this. 0 disables. Needs Rapier. |
break_torque | float | 0 | Force mode: joints break once their torque exceeds this. 0 disables. Needs Rapier. |
break_smoothing | float | 0.5 | Force mode: 0 breaks on a single spike, closer to 1 needs sustained load. |
interior_strength | float | 4 | Joints between two interior bodies with all their neighbours need this many times the threshold. Tears start at the surface or at existing damage. 1 treats every joint the same. |
max_breaks_per_step | int | 3 | Most joints that may break in one physics step. |
Joint / DampedSpringJoint
| Property | Type | Default | Description |
|---|---|---|---|
stiffness | float | 10 | DampedSpringJoint2D.stiffness. |
damping | float | 0.2 | DampedSpringJoint2D.damping. |
rest_length_ratio | float | 0 | Rest length as a ratio of the generated distance. |
length_ratio | float | 0 | Length as a ratio of the generated distance. |
Joint / PinJoint
| Property | Type | Default | Description |
|---|---|---|---|
softness | float | 60 | How far the pins give: the squish. 0 is a rigid truss. |
angular_limit_enabled | bool | false | Bound how far two jointed bodies may twist against each other. |
angular_limit_lower | float | 0 | Lower twist limit, in degrees. |
angular_limit_upper | float | 0 | Upper twist limit, in degrees. |
Shape
| Property | Type | Default | Description |
|---|---|---|---|
radius | float | 20 | Shape size: circle radius is half of it, square side is all of it. Set from vertex_interval. |
shape_type | "Circle" | "Rectangle" | "Circle" | Circles fit the hexagon lattice; squares collide with their own second neighbours once rotated. |
edge_clearance | float | -1 | Least distance a body sits from the outline so its shape stays inside the texture. -1 fits it to the shape automatically, 0 disables. |
Skin
| Property | Type | Default | Description |
|---|---|---|---|
skin_smoothing | float | 0.5 | How far the texture blends across region borders. 0 pins each vertex to its own region. |
RigidBody
| Property | Type | Default | Description |
|---|---|---|---|
mass | float | 0.1 | Mass of every body. |
can_sleep | bool | true | |
gravity_scale | float | 1 | |
constant_force | Vector2 | (0, 0) | |
constant_torque | float | 0 | |
collision_layer | int | 1 | |
collision_mask | int | 1 | |
exclude_array | Array[Node] | [] | Nodes the bodies never collide with. |
rigidbody_scene | PackedScene | Scene with a RigidBody2D root instantiated for every body. | |
physics_material_override | PhysicsMaterial | ||
linear_damp | float | 0 | |
angular_damp | float | 0 |
Debug
| Property | Type | Default | Description |
|---|---|---|---|
debug_draw | flags | 0 | Joints (bit 1): joints coloured by load, blue slack to red at the break threshold or the peak seen. Shapes (bit 2): collision shapes, green, orange once retired. Draws in the editor and in game. |
Methods
| Method | Description |
|---|---|
create_softbody2d(runtime: bool = false) | Regenerate the softbody. In the editor it runs on any property change; at runtime call it with true after setting the properties. |
clear_softbody2d() | Remove every generated child, polygon and bone. |
create_regions() | Generate and draw the regions only. |
get_rigid_bodies() -> Array[SoftBodyChild] | Every body with its rigidbody, bone, joints and shape. |
get_center_body() -> SoftBodyChild | The body nearest the middle. |
get_bones_center_position() -> Vector2 | Centre of all bodies, or the node's position when there are none. |
get_clusters() -> Array | Connected groups of bodies, each an Array[SoftBodyChild]. One after generation, one more per split. |
get_joint_target(joint: Joint2D) -> PhysicsBody2D | The body on the far side of a joint. |
remove_joint(child: SoftBodyChild, joint: Joint2D) | Remove one joint and its reciprocal, split the texture along it, retire a body that lost its last neighbour. |
cut(from: Vector2, to: Vector2) -> int | Remove every joint crossing the global segment; returns how many. |
apply_impulse(impulse: Vector2, position := Vector2.ZERO) | Impulse on every body; position is an offset from each body's centre. |
apply_force(force: Vector2, position := Vector2.ZERO) | Force on every body. |
apply_impulse_at_point(impulse: Vector2, global_point: Vector2, falloff_radius := 0.0) | Impulse from a world point with the correct lever arm; fades to nothing at falloff_radius if set. |
Signals
| Signal | Description |
|---|---|
baked(body_count: int) | Generation finished. |
joint_removed(rigid_body_a: SoftBodyChild, rigid_body_b: SoftBodyChild) | A joint between these two bodies was removed. |
body_detached(rigid_body: SoftBodyChild) | A body lost its last neighbour joint and was retired. |
Enumerations
enum BreakMode
| Value | Description |
|---|---|
NONE | Joints never break. |
DISTANCE | Break on stretch past break_distance_ratio. Any physics engine. |
FORCE | Break on the solver's reaction force past break_force / break_torque. Needs Rapier. |
Constants
| Constant | Value | Description |
|---|---|---|
MAX_REGIONS | 400 | Generation refuses to create more regions than this. |
DEBUG_DRAW_JOINTS | 1 | Bit of debug_draw. |
DEBUG_DRAW_SHAPES | 2 | Bit of debug_draw. |
Inner classes
SoftBodyChild
One body of the softbody: rigidbody: PhysicsBody2D, bone: Bone2D, joints: Array[Joint2D] (the joints parented to this body; every pair of bodies is joined by one joint, which lives on one of the two), shape: CollisionShape2D.