Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[3.x] Fix physics on_floor_body crash #88946

Merged
merged 1 commit into from
Apr 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 23 additions & 10 deletions scene/3d/physics_body.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1077,17 +1077,26 @@ Vector3 KinematicBody::_move_and_slide_internal(const Vector3 &p_linear_velocity
float delta = Engine::get_singleton()->is_in_physics_frame() ? get_physics_process_delta_time() : get_process_delta_time();

Vector3 current_floor_velocity = floor_velocity;
if (on_floor && on_floor_body.is_valid()) {
// This approach makes sure there is less delay between the actual body velocity and the one we saved.
PhysicsDirectBodyState *bs = PhysicsServer::get_singleton()->body_get_direct_state(on_floor_body);

if (on_floor && on_floor_body_rid.is_valid()) {
PhysicsDirectBodyState *bs = nullptr;

// We need to check the on_floor_body still exists before accessing.
// A valid RID is no guarantee that the object has not been deleted.
if (ObjectDB::get_instance(on_floor_body_id)) {
// This approach makes sure there is less delay between the actual body velocity and the one we saved.
bs = PhysicsServer::get_singleton()->body_get_direct_state(on_floor_body_rid);
}

if (bs) {
Transform gt = get_global_transform();
Vector3 local_position = gt.origin - bs->get_transform().origin;
current_floor_velocity = bs->get_velocity_at_local_position(local_position);
} else {
// Body is removed or destroyed, invalidate floor.
current_floor_velocity = Vector3();
on_floor_body = RID();
on_floor_body_rid = RID();
on_floor_body_id = ObjectID();
}
}

Expand All @@ -1098,17 +1107,18 @@ Vector3 KinematicBody::_move_and_slide_internal(const Vector3 &p_linear_velocity
floor_normal = Vector3();
floor_velocity = Vector3();

if (current_floor_velocity != Vector3() && on_floor_body.is_valid()) {
if (current_floor_velocity != Vector3() && on_floor_body_rid.is_valid()) {
Collision floor_collision;
Set<RID> exclude;
exclude.insert(on_floor_body);
exclude.insert(on_floor_body_rid);
if (move_and_collide(current_floor_velocity * delta, p_infinite_inertia, floor_collision, true, false, false, exclude)) {
colliders.push_back(floor_collision);
_set_collision_direction(floor_collision, up_direction, p_floor_max_angle);
}
}

on_floor_body = RID();
on_floor_body_rid = RID();
on_floor_body_id = ObjectID();
Vector3 motion = body_velocity * delta;

// No sliding on first attempt to keep floor motion stable when possible,
Expand Down Expand Up @@ -1186,7 +1196,8 @@ Vector3 KinematicBody::_move_and_slide_internal(const Vector3 &p_linear_velocity
if (Math::acos(col.normal.dot(up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) {
on_floor = true;
floor_normal = col.normal;
on_floor_body = col.collider_rid;
on_floor_body_rid = col.collider_rid;
on_floor_body_id = col.collider;
floor_velocity = col.collider_vel;
if (p_stop_on_slope) {
// move and collide may stray the object a bit because of pre un-stucking,
Expand Down Expand Up @@ -1237,7 +1248,8 @@ void KinematicBody::_set_collision_direction(const Collision &p_collision, const
if (Math::acos(p_collision.normal.dot(p_up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //floor
on_floor = true;
floor_normal = p_collision.normal;
on_floor_body = p_collision.collider_rid;
on_floor_body_rid = p_collision.collider_rid;
on_floor_body_id = p_collision.collider;
floor_velocity = p_collision.collider_vel;
} else if (Math::acos(p_collision.normal.dot(-p_up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //ceiling
on_ceiling = true;
Expand Down Expand Up @@ -1429,7 +1441,8 @@ void KinematicBody::_notification(int p_what) {

// Reset move_and_slide() data.
on_floor = false;
on_floor_body = RID();
on_floor_body_rid = RID();
on_floor_body_id = ObjectID();
on_ceiling = false;
on_wall = false;
colliders.clear();
Expand Down
3 changes: 2 additions & 1 deletion scene/3d/physics_body.h
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,8 @@ class KinematicBody : public PhysicsBody {

Vector3 floor_normal;
Vector3 floor_velocity;
RID on_floor_body;
RID on_floor_body_rid;
ObjectID on_floor_body_id;
bool on_floor;
bool on_ceiling;
bool on_wall;
Expand Down
Loading