‹›
Utility Scripts · Body Penetration

First Working Scene

Copy these events into one controller to drop a 1 kg Box onto a static target.

Start with a project containing the JoltPhysics extension and current DLL. This example uses metres, Z up and 60 Hz physics. The penetrator measures 0.10 × 0.10 × 0.80 m, has a Tip on its bottom face and is tilted by 20°. The low 0.1 N resistance makes the first test easy to observe; it is not a universal material preset.

1. Create event#

GML
// Create event — one controller owns the physics world.
if (!jolt_start({ gravity_z: -9.81, fixed_dt: 1/60 })) {
    show_debug_message(jolt_get_error_message());
    exit;
}

target = jolt_box_create_static(0, 0, 0, 2, 2, 0.4);
target_penetration = jolt_penetration_target(target);
target_penetration.set_forward_force(0.1);
target_penetration.set_backward_force(0.1);
target_penetration.set_max_depth(0.2);
if (!target_penetration.set_enabled(true)) {
    show_debug_message(jolt_get_error_message());
    exit;
}

penetrator = jolt_box_create_dynamic(0, 0, 1.6, 0.10, 0.10, 0.80, { mass: 1 });
penetrator.set_rotation(0, 20, 0);
tip = jolt_penetrator_tip(penetrator);
tip.set_local_position(0, 0, -0.4);
tip.set_local_axis(0, 0, -1);
tip.set_max_angle(40);
tip.set_max_insertion(0.2);
if (!tip.set_enabled(true)) show_debug_message(jolt_get_error_message());
jolt_debug_enable(true);

Box dimensions are full dimensions. A target 0.4 m tall at z=0 has its top surface at z=0.2. A penetrator centre at z=1.6 gives a nominal 1 m drop for the untilted Tip; after tilting, its actual gap is slightly larger. set_rotation(0,20,0) uses degrees.

2. Step event#

GML
// Step event — call jolt_update once for the entire world.
if (is_struct(tip) && tip.is_valid()) {
    if (keyboard_check(vk_space)) {
        penetrator.add_force(0, 0, 30);
    }
}
jolt_update(delta_time / 1000000);

// Drain centrally, then dispatch each snapshot to gameplay systems.
var batch = jolt_penetration_events();
if (is_struct(batch)) {
    for (var i = 0; i < array_length(batch.events); ++i) {
        var event = batch.events[i];
        if (event.type == JoltPenetrationEvent.Start) {
            show_debug_message("Entry: " + string(event.snapshot.target_handle));
        }
        if (event.type == JoltPenetrationEvent.Extracted) {
            show_debug_message("Fully extracted");
        }
    }
}

First let the body fall without holding Space. After entry, hold Space: a 30 N force along world +Z has enough component against the channel axis in this scene to pull the penetrator out. For an arbitrarily oriented target, direct the force against snapshot.axis. After extraction the whole body must clear the target before the Tip rearms. If your project already has a central jolt_update or event consumer, integrate the corresponding code there without duplicating it.

3. Display#

GML
// Draw GUI event
jolt_penetration_debug_text();

// In your existing 3D Draw pass, after setting its view/projection:
jolt_debug_draw(JOLT_DEBUG_SHAPES | JOLT_DEBUG_PENETRATION);

The physics helper does not create a rendered model or camera. Put geometric debug into your existing 3D rendering as described in Debug Draw; the text overview works in Draw GUI. Watch entered, state and depth. Render your normal model using the penetrator body's transform, not the local Tip position.

4. World owner's Clean Up event#

GML
jolt_stop();