Local force and impulse
The helper selects movable particles of one Soft Body in a world-space sphere; it does not follow the body automatically. Creation and setters apply no force. apply queues total force in newtons for the next managed update; repeated calls replace the request rather than multiplying by render FPS. A frame without a physics step keeps it pending. cancel removes it. impulse immediately applies another N·s impulse every call.
Example#
push = jolt_soft_body_force(soft);
push.set_position(0, 0, 3);
push.set_direction(0, 0, -1);
push.set_radius(0.3);
push.set_strength(20);
push.set_impulse(0.5);
// Step, before the existing jolt_update():
if (mouse_check_button(mb_left)) push.apply();
if (keyboard_check_pressed(vk_space)) push.impulse();Usage and limits#
Force is distributed with normalized smooth falloff. Pinned/attached particles are excluded. Selection is volumetric without occlusion or raycast: a tiny sphere can miss the mesh. get_affected_count updates after execution, or immediately for impulse. Queued apply requires jolt_update and is not processed by a bare custom jolt_step loop.
Radius accepts 0.001..1000 m; strength/impulse 0..1000000. set_debug(true) or JOLT_DEBUG_FORCES shows the region. destroy clears the helper and pending force, not its Soft Body. Owner destruction cleans it automatically.
API reference#
Public function and method signatures. Call methods on the returned instance; parameters with defaults are optional.
Related guides#
- Migrating existing code
- Choosing a Soft Body
- Soft sphere
- Volumetric soft box
- Closed model import
- Cloth model and named anchors
- Spatial attachments
- Separate visual mesh
- Wind
- Carrying Soft Bodies
Verified operation contracts#
These contracts distinguish units, return values, errors and lifetime according to the current implementation. Check results: false, 0 and undefined can mean different things for different methods.
| Symbol / owner | Signature | Operation contract |
|---|---|---|
| jolt_soft_body_force | jolt_soft_body_force(soft) | Live JoltBBMODCloth/JoltBBMODSoftBody; returns a new Force or undefined, multiple helpers are allowed. Defaults: position {0, 0, 0}, direction -Z, radius 0.3 m, strength 20 N, impulse 1 N·s, debug false. Creation alone applies nothing. |
| JoltSoftBodyForce.apply | JoltSoftBodyForce.apply() | Boolean; captures current configuration before jolt_update. Latest request wins, repeats during catch-up steps, stays pending in a frame without a step, clears after a processed frame. Free particles inside radius receive normalized smoothstep force shares; pins/attachments are excluded. |
| JoltSoftBodyForce.cancel | JoltSoftBodyForce.cancel() | Boolean; removes a pending apply request, does not undo an already applied impulse/force. Requires a live helper. |
| JoltSoftBodyForce.destroy | JoltSoftBodyForce.destroy() | Boolean, repeated destruction is safe. Removes only the helper, not the soft body or rigid host. Wind disables airflow, Force cancels the pending request, Attachment releases its particle selection. |
| JoltSoftBodyForce.get_affected_count | JoltSoftBodyForce.get_affected_count() | Particle count from the last successfully submitted request, initially 0. apply updates it at a physics step; configuration alone does not refresh it. |
| JoltSoftBodyForce.get_debug | JoltSoftBodyForce.get_debug() | Stored debug Boolean; does not itself check validity. |
| JoltSoftBodyForce.get_direction | JoltSoftBodyForce.get_direction() | Copy of stored unit world {x, y, z}; configuration getter, does not itself check helper validity. |
| JoltSoftBodyForce.get_impulse | JoltSoftBodyForce.get_impulse() | Total impulse: stored number in N·s; no helper validity check. |
| JoltSoftBodyForce.get_position | JoltSoftBodyForce.get_position() | Copy of stored world {x, y, z} in m; configuration getter without a validity check. |
| JoltSoftBodyForce.get_radius | JoltSoftBodyForce.get_radius() | Selection radius: stored number in m; no helper validity check. |
| JoltSoftBodyForce.get_strength | JoltSoftBodyForce.get_strength() | Total force: stored number in N; no helper validity check. |
| JoltSoftBodyForce.impulse | JoltSoftBodyForce.impulse() | Boolean; immediately applies total impulse distributed by smoothstep weights to free particles inside radius. Zero strength or an empty selection succeeds with 0 affected. Not a repeated apply. |
| JoltSoftBodyForce.is_valid | JoltSoftBodyForce.is_valid() | Boolean; both helper and its soft body must be live. Destroying the soft body invalidates the helper. |
| JoltSoftBodyForce.set_debug | JoltSoftBodyForce.set_debug(v) | Boolean coercion; default false. Returns true/false, requires a live helper. Diagnostics only. |
| JoltSoftBodyForce.set_direction | JoltSoftBodyForce.set_direction(x,y,z) | Finite world x/y/z, absolute values ≤ 1e9, length ≥ 1e-6. Normalizes direction; Boolean, false for an invalid helper. |
| JoltSoftBodyForce.set_impulse | JoltSoftBodyForce.set_impulse(v) | Total impulse: finite 0..1000000 N·s, default 1; Boolean. The amount is total across the selection, not multiplied by particle count. |
| JoltSoftBodyForce.set_position | JoltSoftBodyForce.set_position(x,y,z) | Finite world x/y/z in m, absolute values ≤ 1e9; Boolean. Changes future requests, not an already captured apply snapshot. |
| JoltSoftBodyForce.set_radius | JoltSoftBodyForce.set_radius(v) | Selection radius: finite 0.001..1000 m, default 0.3; Boolean. The amount is total across the selection, not multiplied by particle count. |
| JoltSoftBodyForce.set_strength | JoltSoftBodyForce.set_strength(v) | Total force: finite 0..1000000 N, default 20; Boolean. The amount is total across the selection, not multiplied by particle count. |