‹
Constraints

Constraint Lifecycle

Explains validity, ownership, disabling, collision filtering, dependency invalidation and safe cleanup.

A managed JoltConstraint owns one world-scoped generational native handle. It references connected bodies but never owns their GML wrappers or gameplay data.

States#

Stateis_valid()Meaning
Alive and enabledtrueThe native constraint participates in solving.
Alive and disabledtrueThe resource and settings remain, but it does not participate in solving.
DestroyedfalseThe handle is released and becomes 0 on the wrapper.
Dependency destroyedfalseDestroying an attached body automatically removes its constraints first.
Runtime stoppedfalsejolt_stop() invalidates resources from the old default world.

Ownership rules#

  • destroy() destroys only the constraint, never either body.
  • destroy() is idempotent and safe to repeat on an already released wrapper.
  • A stale generational handle cannot address a later constraint that reuses the same internal slot.
  • All body-to-body constraints must remain in the same managed default world as their bodies.
  • World constraints reference Jolt's immutable fixed body internally and one user body externally.

Disable versus destroy#

GML
joint.set_enabled(false); // keep limits and motor settings

// Later:
joint.set_enabled(true);

// Permanent release:
joint.destroy();

Disabling is appropriate for a mechanism that will be reused. Destroying is appropriate when the relationship has ended and should release its native solver resource.

Connected-body collision#

  • collision:false or set_collision_enabled(false) suppresses only the connected user-body pair.
  • Suppression is reference-counted: destroying one of several suppressing constraints does not re-enable the pair prematurely.
  • Changing the setting invalidates cached contacts and wakes the affected bodies.
  • World constraints always report collision disabled because there is no second user collision body.

Safe cleanup#

GML
if (is_struct(joint) && joint.is_valid()) {
    joint.destroy();
}

body_a.destroy();
body_b.destroy();

// Global managed cleanup is also ordered and idempotent.
jolt_stop();

Error handling#

GML
var joint = jolt_hinge(a, b, 0,0,2, 0,0,1);
if (is_undefined(joint)) {
    var error = jolt_get_error();
    show_debug_message(string(error.code) + " / " + error.context + ": " + error.message);
}

Manual cleanup order#

Release dependent constraints before their bodies, then release reusable shape/layer resources before the world and runtime. jolt_stop() performs the managed order automatically and safely when repeated.

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 / ownerSignatureOperation contract
JoltConstraint.destroyJoltConstraint.destroy()Boolean; destroys the constraint, not its bodies. Repeated destruction of an already invalid wrapper returns true; a native error can return false.
JoltConstraint.get_collision_enabledJoltConstraint.get_collision_enabled()Collision between the two attached bodies. Setter Boolean success, getter Boolean state; a world constraint always reads false and its setter succeeds without enabling collision. Not a global layer filter.
JoltConstraint.get_current_lengthJoltConstraint.get_current_length()Pulley only: minimum/maximum/current combined length in m (including pulley ratio). 0 on error.
JoltConstraint.get_enabledJoltConstraint.get_enabled()Constraint activation, not destruction. Setter returns Boolean success; getter Boolean state, also false on error. Requires a live constraint.
JoltConstraint.get_frictionJoltConstraint.get_friction(axis)SixDOF axis 0..5; N for translation, N·m for rotation; 0 for invalid wrapper/type, inspect native errors separately.
JoltConstraint.get_impulsesJoltConstraint.get_impulses()SixDOF: {translation, rotation, motor_translation, motor_rotation}, each {x, y, z}, latest solver impulses N·s / N·m·s. undefined for invalid wrapper/type; inspect native errors separately.
JoltConstraint.get_max_lengthJoltConstraint.get_max_length()Pulley only: minimum/maximum/current combined length in m (including pulley ratio). 0 on error.
JoltConstraint.get_min_lengthJoltConstraint.get_min_length()Pulley only: minimum/maximum/current combined length in m (including pulley ratio). 0 on error.
JoltConstraint.get_native_handleJoltConstraint.get_native_handle()Live constraint handle or 0.
JoltConstraint.get_positionJoltConstraint.get_position()Slider displacement or Path distance along the path in m, not {x, y, z}. 0 on error.
JoltConstraint.get_sixdof_debug_frameJoltConstraint.get_sixdof_debug_frame()SixDOF diagnostic struct: world anchor and axis_x/y/z; relative_position/orientation and target_position/orientation in constraint space. Positions m, orientations XYZW. undefined for invalid wrapper/type; read-only, no solver change.
JoltConstraint.get_target_angular_velocityJoltConstraint.get_target_angular_velocity()SixDOF: {x, y, z} in constraint space in °/s. Getter does not capture every native error; validate type/liveness first and inspect the error state.
JoltConstraint.get_target_positionJoltConstraint.get_target_position()SixDOF: {x, y, z} in constraint space in m. Getter does not capture every native error; validate type/liveness first and inspect the error state.
JoltConstraint.get_target_velocityJoltConstraint.get_target_velocity()SixDOF: {x, y, z} in constraint space in m/s. Getter does not capture every native error; validate type/liveness first and inspect the error state.
JoltConstraint.is_validJoltConstraint.is_valid()Boolean checking the native constraint and original world; destruction of an attached body invalidates the constraint.
JoltConstraint.set_collision_enabledJoltConstraint.set_collision_enabled(enabled)Collision between the two attached bodies. Setter Boolean success, getter Boolean state; a world constraint always reads false and its setter succeeds without enabling collision. Not a global layer filter.
JoltConstraint.set_enabledJoltConstraint.set_enabled(enabled)Constraint activation, not destruction. Setter returns Boolean success; getter Boolean state, also false on error. Requires a live constraint.
JoltConstraint.set_frictionJoltConstraint.set_friction(axis,value)SixDOF axis 0..5; finite nonnegative force limit (axes 0..2, N) or torque limit (3..5, N·m). Boolean. Setting a limit alone does not enable a motor.
JoltConstraint.set_lengthJoltConstraint.set_length(minimum, maximum)Pulley only: finite 0 ≤ min ≤ max in m for combined length. Boolean.
JoltConstraint.set_target_angular_velocityJoltConstraint.set_target_angular_velocity(x,y,z)SixDOF: finite x/y/z in constraint space in °/s; Boolean. Setting a target alone does not enable individual motors.
JoltConstraint.set_target_positionJoltConstraint.set_target_position(x,y,z)SixDOF: finite x/y/z in constraint space in m; Boolean. Setting a target alone does not enable individual motors.
JoltConstraint.set_target_velocityJoltConstraint.set_target_velocity(x,y,z)SixDOF: finite x/y/z in constraint space in m/s; Boolean. Setting a target alone does not enable individual motors.