Skip to content
This repository has been archived by the owner on Jun 29, 2024. It is now read-only.

When "rough" is checked and friction differs, collision causes objects to disappear #110

Open
pthrasher opened this issue Mar 21, 2024 · 2 comments
Labels
bug Something isn't working

Comments

@pthrasher
Copy link

Describe the bug
When physics materials differ in 2d collisions, and rough is checked on one of the materials, collision happens, and then the body appears to be removed from the world.

To Reproduce
Steps to reproduce the behavior:

  1. make a rigidbody2d and add a new physics material with < 1 friction.
  2. make a static body and add a new physics material with a greater friction from above, and check "rough"
  3. allow rigid body to freely fall onto static body.

Expected behavior
I expected the rigidbody to appropriately react to the static body rather than disappearing.

Project
PhysMatProblem.zip

Versions (please complete the following information):

  • OS MacOS Sonoma 14.2.1
  • Godot 4.2.1
  • Box2d 0.9.9
@pthrasher pthrasher added the bug Something isn't working label Mar 21, 2024
@MrEgggga
Copy link

MrEgggga commented May 1, 2024

it seems like box2d's friction calculation works completely different from godot physics's calculation such that the "rough" field means nothing. if you do need the roughness feature it seems like you'd have to compile your own version of box2d (although it seems like this wouldn't be too hard -- box2d's friction calculation is about one line long). in any case, though, the thing definitely shouldn't fail in the way it does. i'm planning on modifying this extension for my own game so i might be able to figure out why that happens.

@MrEgggga
Copy link

MrEgggga commented May 1, 2024

i think i've figured it out:

  • physics materials have a function get_computed_friction which usually returns the friction value, but when the material is rough this returns the negative of the friction value. it seems like the computed friction is the one that is actually used everywhere, so this is the one that i'm guessing gets passed into box2d.
  • in order to calculate the coefficient of friction between two physics bodies, godot physics takes the absolute value of the minimum of the two friction values of the bodies(' materials). since computed friction of rough materials is negative, this does the roughness calculation as described in the godot docs, just in a "clever" way. here's the code that does this.
  • box2d's friction calculation works differently -- instead of calculating the minimum it calculates the geometric mean of the two friction values (i.e. the square root of the product of the two values). you can see the reasoning behind this in a very nice comment above the function. the problem here is that the function is getting negative values when materials are rough, and the square root of a negative value is NaN as far as computers are concerned. (amusingly, this doesn't happen if both materials are rough.)

there are two solutions to this:

  1. change the box2d wrapper to give box2d the absolute value of the computed friction so we don't have to worry about negative values. this is probably the best solution for the main version of this extension. i'll probably make a pull request for this tomorrow-ish.
  2. make a fork of box2d that changes its friction calculation to work like godot physics. this is good if you want to keep the "rough surfaces" feature, but not what should be done for this version of the repository. i'm planning on doing this for my game.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants