Fix physics on_floor_body crash
Physics body previously stored the RID of a collision object and accessed it on the next frame, leading to a crash if the object had been deleted. This PR stores the ObjectID in addition to the RID, and checks the object still exists prior to access.
This commit is contained in:
parent
50fa1896b8
commit
9a9dccbaa2
2 changed files with 25 additions and 11 deletions
|
@ -1077,9 +1077,17 @@ 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()) {
|
||||
|
||||
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.
|
||||
PhysicsDirectBodyState *bs = PhysicsServer::get_singleton()->body_get_direct_state(on_floor_body);
|
||||
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;
|
||||
|
@ -1087,7 +1095,8 @@ Vector3 KinematicBody::_move_and_slide_internal(const Vector3 &p_linear_velocity
|
|||
} 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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
|
|
@ -292,7 +292,8 @@ private:
|
|||
|
||||
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;
|
||||
|
|
Loading…
Reference in a new issue