Fix errors in CharacterBody when floor is destroyed or removed
In all physics servers, body_get_direct_state() now silently returns nullptr when the body has been already freed or is removed from space, so the client code can detect this state and invalidate the body rid. In 2D, there is no change in behavior (just no more errors). In 3D, the Bullet server returned a valid direct body state when the body was removed from the physics space, but in this case it didn't make sense to use the information from the body state.
This commit is contained in:
parent
e8870ddefc
commit
bfd0d33244
7 changed files with 35 additions and 4 deletions
|
@ -346,7 +346,7 @@
|
||||||
<return type="PhysicsDirectBodyState2D" />
|
<return type="PhysicsDirectBodyState2D" />
|
||||||
<argument index="0" name="body" type="RID" />
|
<argument index="0" name="body" type="RID" />
|
||||||
<description>
|
<description>
|
||||||
Returns the [PhysicsDirectBodyState2D] of the body.
|
Returns the [PhysicsDirectBodyState2D] of the body. Returns [code]null[/code] if the body is destroyed or removed from the physics space.
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
<method name="body_get_max_contacts_reported" qualifiers="const">
|
<method name="body_get_max_contacts_reported" qualifiers="const">
|
||||||
|
|
|
@ -320,7 +320,7 @@
|
||||||
<return type="PhysicsDirectBodyState3D" />
|
<return type="PhysicsDirectBodyState3D" />
|
||||||
<argument index="0" name="body" type="RID" />
|
<argument index="0" name="body" type="RID" />
|
||||||
<description>
|
<description>
|
||||||
Returns the [PhysicsDirectBodyState3D] of the body.
|
Returns the [PhysicsDirectBodyState3D] of the body. Returns [code]null[/code] if the body is destroyed or removed from the physics space.
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
<method name="body_get_max_contacts_reported" qualifiers="const">
|
<method name="body_get_max_contacts_reported" qualifiers="const">
|
||||||
|
|
|
@ -837,8 +837,17 @@ void BulletPhysicsServer3D::body_set_ray_pickable(RID p_body, bool p_enable) {
|
||||||
}
|
}
|
||||||
|
|
||||||
PhysicsDirectBodyState3D *BulletPhysicsServer3D::body_get_direct_state(RID p_body) {
|
PhysicsDirectBodyState3D *BulletPhysicsServer3D::body_get_direct_state(RID p_body) {
|
||||||
|
if (!rigid_body_owner.owns(p_body)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
RigidBodyBullet *body = rigid_body_owner.get_or_null(p_body);
|
RigidBodyBullet *body = rigid_body_owner.get_or_null(p_body);
|
||||||
ERR_FAIL_COND_V(!body, nullptr);
|
ERR_FAIL_COND_V(!body, nullptr);
|
||||||
|
|
||||||
|
if (!body->get_space()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
return BulletPhysicsDirectBodyState3D::get_singleton(body);
|
return BulletPhysicsDirectBodyState3D::get_singleton(body);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1101,6 +1101,10 @@ bool CharacterBody2D::move_and_slide() {
|
||||||
if (bs) {
|
if (bs) {
|
||||||
Vector2 local_position = gt.elements[2] - bs->get_transform().elements[2];
|
Vector2 local_position = gt.elements[2] - bs->get_transform().elements[2];
|
||||||
current_platform_velocity = bs->get_velocity_at_local_position(local_position);
|
current_platform_velocity = bs->get_velocity_at_local_position(local_position);
|
||||||
|
} else {
|
||||||
|
// Body is removed or destroyed, invalidate floor.
|
||||||
|
current_platform_velocity = Vector2();
|
||||||
|
platform_rid = RID();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
current_platform_velocity = Vector2();
|
current_platform_velocity = Vector2();
|
||||||
|
|
|
@ -1145,6 +1145,10 @@ bool CharacterBody3D::move_and_slide() {
|
||||||
if (bs) {
|
if (bs) {
|
||||||
Vector3 local_position = gt.origin - bs->get_transform().origin;
|
Vector3 local_position = gt.origin - bs->get_transform().origin;
|
||||||
current_platform_velocity = bs->get_velocity_at_local_position(local_position);
|
current_platform_velocity = bs->get_velocity_at_local_position(local_position);
|
||||||
|
} else {
|
||||||
|
// Body is removed or destroyed, invalidate floor.
|
||||||
|
current_platform_velocity = Vector3();
|
||||||
|
platform_rid = RID();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
current_platform_velocity = Vector3();
|
current_platform_velocity = Vector3();
|
||||||
|
|
|
@ -963,10 +963,17 @@ bool GodotPhysicsServer2D::body_test_motion(RID p_body, const MotionParameters &
|
||||||
PhysicsDirectBodyState2D *GodotPhysicsServer2D::body_get_direct_state(RID p_body) {
|
PhysicsDirectBodyState2D *GodotPhysicsServer2D::body_get_direct_state(RID p_body) {
|
||||||
ERR_FAIL_COND_V_MSG((using_threads && !doing_sync), nullptr, "Body state is inaccessible right now, wait for iteration or physics process notification.");
|
ERR_FAIL_COND_V_MSG((using_threads && !doing_sync), nullptr, "Body state is inaccessible right now, wait for iteration or physics process notification.");
|
||||||
|
|
||||||
|
if (!body_owner.owns(p_body)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
GodotBody2D *body = body_owner.get_or_null(p_body);
|
GodotBody2D *body = body_owner.get_or_null(p_body);
|
||||||
ERR_FAIL_COND_V(!body, nullptr);
|
ERR_FAIL_COND_V(!body, nullptr);
|
||||||
|
|
||||||
ERR_FAIL_COND_V(!body->get_space(), nullptr);
|
if (!body->get_space()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
ERR_FAIL_COND_V_MSG(body->get_space()->is_locked(), nullptr, "Body state is inaccessible right now, wait for iteration or physics process notification.");
|
ERR_FAIL_COND_V_MSG(body->get_space()->is_locked(), nullptr, "Body state is inaccessible right now, wait for iteration or physics process notification.");
|
||||||
|
|
||||||
return body->get_direct_state();
|
return body->get_direct_state();
|
||||||
|
|
|
@ -881,10 +881,17 @@ bool GodotPhysicsServer3D::body_test_motion(RID p_body, const MotionParameters &
|
||||||
PhysicsDirectBodyState3D *GodotPhysicsServer3D::body_get_direct_state(RID p_body) {
|
PhysicsDirectBodyState3D *GodotPhysicsServer3D::body_get_direct_state(RID p_body) {
|
||||||
ERR_FAIL_COND_V_MSG((using_threads && !doing_sync), nullptr, "Body state is inaccessible right now, wait for iteration or physics process notification.");
|
ERR_FAIL_COND_V_MSG((using_threads && !doing_sync), nullptr, "Body state is inaccessible right now, wait for iteration or physics process notification.");
|
||||||
|
|
||||||
|
if (!body_owner.owns(p_body)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
GodotBody3D *body = body_owner.get_or_null(p_body);
|
GodotBody3D *body = body_owner.get_or_null(p_body);
|
||||||
ERR_FAIL_NULL_V(body, nullptr);
|
ERR_FAIL_NULL_V(body, nullptr);
|
||||||
|
|
||||||
ERR_FAIL_NULL_V(body->get_space(), nullptr);
|
if (!body->get_space()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
ERR_FAIL_COND_V_MSG(body->get_space()->is_locked(), nullptr, "Body state is inaccessible right now, wait for iteration or physics process notification.");
|
ERR_FAIL_COND_V_MSG(body->get_space()->is_locked(), nullptr, "Body state is inaccessible right now, wait for iteration or physics process notification.");
|
||||||
|
|
||||||
return body->get_direct_state();
|
return body->get_direct_state();
|
||||||
|
|
Loading…
Reference in a new issue