You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-12-06 17:25:19 +00:00
Fix multiple issues with 2D & 3D physics
- Use `NOTIFICATION_ENTER`/`EXIT_WORLD` for `Area` (intead of `*_TREE`). - Now both bodies' and areas' constraints are cleaned up. - And now also that happens as soon as the space is set to null (i.e., when exiting the tree) instead of only at freeing time. - When clearing constraints, the loop goes on to the next if the current is already released, instead of breaking. - When one has been already released, no error is shown from now on, as it's something expected, since a pair (our kind of constraint of interest) can be freed by any of its involved collision objects and the other will try again. - Implement index shifting (or marking as -1) for shapes indices in collision pairs shapes are removed. - Standarize behavior of bodies and areas so that anything that invalidates a given pair gives the same result (collision mask, actual collision, etc); for instance, triggering area enter/exit signals. - Add missing member initializations. - Extend the new-space-equals-area/body-current-space test to every case. - Fix 3D ray-casts early accepting Areas (skipping the mask check). - Fix unpairing of large elements (2D's `BroadPhase2DHashGrid`). Some of these prevent random crashes caused by constraints with dangling pointers to involved objects. Fixes #8856. Fixes #7589. Fixes #6676. And maybe others.
This commit is contained in:
@@ -222,13 +222,25 @@ void PhysicsServerSW::area_set_space(RID p_area, RID p_space) {
|
||||
|
||||
AreaSW *area = area_owner.get(p_area);
|
||||
ERR_FAIL_COND(!area);
|
||||
|
||||
SpaceSW *space = NULL;
|
||||
if (p_space.is_valid()) {
|
||||
space = space_owner.get(p_space);
|
||||
ERR_FAIL_COND(!space);
|
||||
}
|
||||
|
||||
if (area->get_space() == space)
|
||||
return; //pointless
|
||||
|
||||
area->set_space(space);
|
||||
|
||||
for (Set<ConstraintSW *>::Element *E = area->get_constraints().front(); E; E = E->next()) {
|
||||
RID self = E->get()->get_self();
|
||||
if (!self.is_valid())
|
||||
continue;
|
||||
free(self);
|
||||
}
|
||||
area->clear_constraints();
|
||||
};
|
||||
|
||||
RID PhysicsServerSW::area_get_space(RID p_area) const {
|
||||
@@ -463,6 +475,7 @@ void PhysicsServerSW::body_set_space(RID p_body, RID p_space) {
|
||||
|
||||
BodySW *body = body_owner.get(p_body);
|
||||
ERR_FAIL_COND(!body);
|
||||
|
||||
SpaceSW *space = NULL;
|
||||
|
||||
if (p_space.is_valid()) {
|
||||
@@ -471,9 +484,17 @@ void PhysicsServerSW::body_set_space(RID p_body, RID p_space) {
|
||||
}
|
||||
|
||||
if (body->get_space() == space)
|
||||
return; //pointles
|
||||
return; //pointless
|
||||
|
||||
body->set_space(space);
|
||||
|
||||
for (Map<ConstraintSW *, int>::Element *E = body->get_constraint_map().front(); E; E = E->next()) {
|
||||
RID self = E->key()->get_self();
|
||||
if (!self.is_valid())
|
||||
continue;
|
||||
free(self);
|
||||
}
|
||||
body->clear_constraint_map();
|
||||
};
|
||||
|
||||
RID PhysicsServerSW::body_get_space(RID p_body) const {
|
||||
@@ -1302,19 +1323,13 @@ void PhysicsServerSW::free(RID p_rid) {
|
||||
// if (body->get_direct_state_query())
|
||||
// _clear_query(body->get_direct_state_query());
|
||||
|
||||
body->set_space(NULL);
|
||||
body_set_space(p_rid, RID());
|
||||
|
||||
while (body->get_shape_count()) {
|
||||
|
||||
body->remove_shape(0);
|
||||
}
|
||||
|
||||
while (body->get_constraint_map().size()) {
|
||||
RID self = body->get_constraint_map().front()->key()->get_self();
|
||||
ERR_FAIL_COND(!self.is_valid());
|
||||
free(self);
|
||||
}
|
||||
|
||||
body_owner.free(p_rid);
|
||||
memdelete(body);
|
||||
|
||||
@@ -1325,7 +1340,7 @@ void PhysicsServerSW::free(RID p_rid) {
|
||||
// if (area->get_monitor_query())
|
||||
// _clear_query(area->get_monitor_query());
|
||||
|
||||
area->set_space(NULL);
|
||||
area_set_space(p_rid, RID());
|
||||
|
||||
while (area->get_shape_count()) {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user