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

Colliding Rigidbody2Ds cause FPS drop even if their masks/layers don't match #45824

Closed
Tracked by #45334
KoBeWi opened this issue Feb 8, 2021 · 1 comment · Fixed by #45989
Closed
Tracked by #45334

Colliding Rigidbody2Ds cause FPS drop even if their masks/layers don't match #45824

KoBeWi opened this issue Feb 8, 2021 · 1 comment · Fixed by #45989

Comments

@KoBeWi
Copy link
Member

KoBeWi commented Feb 8, 2021

Godot version:

3.2.4 rc1

Minimal reproduction project:

rigidbody_mask_bug.zip
Compare Slow.tscn and NotSlow.tscn. In both the collision layers/masks are set to 0, but if the bodies are colliding, there is an extreme FPS drop.

@HenryWConklin
Copy link
Contributor

HenryWConklin commented Feb 13, 2021

From some quick profiling, looks like the culprit is BroadPhase2DHashGrid::_check_motion

  14.91%  godot.linuxbsd.  godot.linuxbsd.tools.64             [.] BroadPhase2DHashGrid::_check_motion
  10.23%  godot.linuxbsd.  godot.linuxbsd.tools.64             [.] Rect2::intersects
   8.04%  godot.linuxbsd.  godot.linuxbsd.tools.64             [.] CollisionObject2DSW::test_collision_mask

Looks like it's not short-circuiting on the collision masks, so it's always checking the AABB collisions:

void BroadPhase2DHashGrid::_check_motion(Element *p_elem) {
for (Map<Element *, PairData *>::Element *E = p_elem->paired.front(); E; E = E->next()) {
bool physical_collision = p_elem->aabb.intersects(E->key()->aabb);
bool logical_collision = p_elem->owner->test_collision_mask(E->key()->owner);
if (physical_collision) {
if (!E->get()->colliding || (logical_collision && !E->get()->ud && pair_callback)) {
E->get()->ud = pair_callback(p_elem->owner, p_elem->subindex, E->key()->owner, E->key()->subindex, pair_userdata);
} else if (E->get()->colliding && !logical_collision && E->get()->ud && unpair_callback) {
unpair_callback(p_elem->owner, p_elem->subindex, E->key()->owner, E->key()->subindex, E->get()->ud, unpair_userdata);
E->get()->ud = nullptr;
}
E->get()->colliding = true;
} else { // No physcial_collision
if (E->get()->colliding && unpair_callback) {
unpair_callback(p_elem->owner, p_elem->subindex, E->key()->owner, E->key()->subindex, E->get()->ud, unpair_userdata);
}
E->get()->colliding = false;
}
}
}

I might pick this up tomorrow if no one else takes it.

EDIT,next day:
Turns out the slow part is actually just dereferencing E->get(), so short circuiting there doesn't really help. Solution turns out to be a bit more complicated but I think I almost have it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants