Update kinematic character controller to apply forces to dynamic bodies

the character collides with
This commit is contained in:
reo 2025-12-15 22:44:44 +03:00
parent b50a60755a
commit 6ac8e8f503

View file

@ -1,7 +1,7 @@
use glam::{Quat, Vec3}; use glam::{Quat, Vec3};
use rapier3d::prelude::{nalgebra, ColliderBuilder, QueryFilter, RigidBodyBuilder}; use rapier3d::prelude::{nalgebra, ColliderBuilder, QueryFilter, RigidBodyBuilder, RigidBodyType};
use rapier3d::prelude::vector; use rapier3d::prelude::vector;
use rapier3d::control::KinematicCharacterController as RapierKinematicCharacterController; use rapier3d::control::{CharacterCollision, KinematicCharacterController as RapierKinematicCharacterController};
use rapier3d::na::{Isometry3, Vector3}; use rapier3d::na::{Isometry3, Vector3};
use winit::event::DeviceEvent::MouseMotion; use winit::event::DeviceEvent::MouseMotion;
use winit::event::Event; use winit::event::Event;
@ -53,7 +53,7 @@ impl System for KinematicCharacterController {
)); ));
self.speed = 5.0; self.speed = 5.0;
self.sensitivity = 0.1; self.sensitivity = 0.05;
self.gravity = -9.81; self.gravity = -9.81;
self.max_fall_speed = -50.0; self.max_fall_speed = -50.0;
self.vertical_velocity = 0.0; self.vertical_velocity = 0.0;
@ -141,13 +141,14 @@ impl System for KinematicCharacterController {
let mut total_displacement = self.desired_movement; let mut total_displacement = self.desired_movement;
total_displacement.y += self.vertical_velocity * pctx.time_ctx.fixed_dt; total_displacement.y += self.vertical_velocity * pctx.time_ctx.fixed_dt;
let mut collisions: Vec<CharacterCollision> = Vec::new();
let corrected_movement = self.character_controller.move_shape( let corrected_movement = self.character_controller.move_shape(
pctx.time_ctx.fixed_dt, pctx.time_ctx.fixed_dt,
&query_pipeline, &query_pipeline,
&*self.character_collider.shape, &*self.character_collider.shape,
&Isometry3::from(self.last_position), &Isometry3::from(self.last_position),
vector![total_displacement.x, total_displacement.y, total_displacement.z], vector![total_displacement.x, total_displacement.y, total_displacement.z],
|_| {}, |collision| collisions.push(collision),
); );
// update character rigid body with the new translation. // update character rigid body with the new translation.
@ -165,6 +166,22 @@ impl System for KinematicCharacterController {
} }
} }
// apply impulses to dynamic bodies the character collided with
let character_push_force = 50.0;
for collision in collisions {
if let Some(collider) = p.collider_set.get(collision.handle) {
if let Some(rb_handle) = collider.parent() {
if let Some(rb) = p.rigid_body_set.get_mut(rb_handle) {
if rb.body_type() == RigidBodyType::Dynamic {
let push_direction = -collision.hit.normal1.into_inner();
let impulse = push_direction * character_push_force * pctx.time_ctx.fixed_dt;
rb.apply_impulse(impulse, true);
}
}
}
}
}
self.desired_movement = Vec3::ZERO; self.desired_movement = Vec3::ZERO;
} }
} }