Skip to content

Support custom integration and using LinearVelocity for KCCs#899

Merged
Jondolf merged 2 commits intomainfrom
mns-velocity
Nov 26, 2025
Merged

Support custom integration and using LinearVelocity for KCCs#899
Jondolf merged 2 commits intomainfrom
mns-velocity

Conversation

@Jondolf
Copy link
Member

@Jondolf Jondolf commented Nov 26, 2025

Objective

Currently, for KCC movement, users must keep LinearVelocity at zero and manage their own externally stored velocity. Otherwise, you will end up applying the velocity twice, once by the move-and-slide algorithm, and once by the built-in position integration.

This is inconvenient, and also causes potentially incorrect collision response for dynamic bodies that bump into the kinematic body, as the contact won't consider relative velocity properly. Not good!

It would be good if users could use LinearVelocity even for KCCs, and simply change the way it is applied.

Solution

Add CustomVelocityIntegration and CustomPositionIntegration components for disabling Avian's built-in integration logic. This allows users to implement their own movement driven by LinearVelocity and move-and-slide.

Testing

Ran move_and_slide_2d and move_and_slide_3d.


Showcase

Add the CustomPositionIntegration component to disable Avian's own position updates based on velocity:

commands.spawn((
    Character,
    RigidBody::Kinematic,
    Collider::from(shape),
    // We want to control position updates manually using move and slide.
    CustomPositionIntegration,
));

Movement systems can then simply modify LinearVelocity. In a way, this also makes many systems generic over dynamic and kinematic character controllers.

fn character_movement(
    mut query: Query<&mut LinearVelocity, With<Character>>,
    input: Res<ButtonInput<KeyCode>>,
) {
    for mut lin_vel in &mut query {
        // Determine movement velocity from input
        let mut delta_vel = Vec2::ZERO;
        if input.pressed(KeyCode::KeyW) {
            delta_vel += Vec2::Y
        }
        if input.pressed(KeyCode::KeyS) {
            delta_vel += Vec2::NEG_Y
        }
        if input.pressed(KeyCode::KeyA) {
            delta_vel += Vec2::NEG_X
        }
        if input.pressed(KeyCode::KeyD) {
            delta_vel += Vec2::X
        }
        delta_vel = delta_vel.normalize_or_zero();
        delta_vel *= 100.0;
        if input.pressed(KeyCode::ShiftLeft) {
            delta_vel *= 2.0;
        }

        lin_vel.0 += delta_vel.adjust_precision();
    }
}

You can then just run move_and_slide in some system, using LinearVelocity as the input velocity, and write the output velocity to LinearVelocity.

@Jondolf Jondolf added this to the 0.5 milestone Nov 26, 2025
@Jondolf Jondolf added C-Usability A quality-of-life improvement that makes Avian easier to use A-Character-Controller Relates to character controllers D-Straightforward Simple bug fixes and API improvements, docs, test and examples labels Nov 26, 2025
@Jondolf Jondolf merged commit 986c2bb into main Nov 26, 2025
6 checks passed
@Jondolf Jondolf deleted the mns-velocity branch November 26, 2025 15:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-Character-Controller Relates to character controllers C-Usability A quality-of-life improvement that makes Avian easier to use D-Straightforward Simple bug fixes and API improvements, docs, test and examples

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants