-
-
Notifications
You must be signed in to change notification settings - Fork 97
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
Change physics material friction/bounce combine modes to match other engines #11715
Comments
At the same time, another discussion that we need to have about physics materials is static friction vs dynamic friction. Most physics systems have both, but Godot only has one friction value. Static friction is the friction required for an object to start moving, while dynamic friction is the friction when already moving. Realistic objects have a higher static friction than dynamic friction, as an emergent phenomena of the microscopic grooves in the materials settling into each other. |
In my opinion the dual friction values are legacy from PhysX. This split is not a useful feature and it adds complexity and overhead to the solver that all users pay for but likely none benefit from. It is hard enough for designers to understand static friction as it is. I don't think asking them to tune two parameters is justified in this case. What is the scenario where a game would benefit from the lower dynamic friction? The way friction and materials are simulated in game physics is very far from real materials. For example, friction can be anisotropic or temperature dependent. The way surface geometry is modelled is also highly simplified. The friction mixing precedence rules seem arbitrary to me. Again, I think presenting these combine modes to designers in frequent tuning scenarios is not justified. In Box2D I've implemented an optional mixing callback that takes the two friction (restitution) values and a surface type integer and returns a mixed value. typedef float b2FrictionCallback( float frictionA, int materialA, float frictionB, int materialB );
typedef float b2RestitutionCallback( float restitutionA, int materialA, float restitutionB, int materialB ); These intentionally provide no context to keep them light weight and thread safe. Most of the time the user will not care about the combine mode if good defaults are used. A good default for friction is In general I recommend against trying to have cross platform data for physics in a format such as gltf. Different choices will work better in different engines. Different physics engines will have different features and the even similar features may work differently. Suppose I carefully author a physics setup in Blender and it is using Bullet. The behavior, performance, and stability may be completely different when setup in PhysX, Jolt, or Havok. The feature set can also be different. So all that careful tuning done in Blender becomes meaningless when the setup is brought into the game engine. Physics engines are not interchangeable. |
@erincatto There will be glTF physics. Even if the results are slightly different in some engines, at least most of the data is transferable in a mostly correct way, which means that fewer changes are required after import, which is highly useful. It's better to tweak after import than to re-do all of the physics properties of a 3D asset. The point about the most useful defaults makes sense. Thinking about practical examples, a bouncy ball on a non-bouncy floor would be best modeled by the maximum operation, so I'd indeed agree with maximum as the default for the restitution combine mode. This does lead me to wonder, should there be 2 sets of enums with 2 sets of precedences, so that we can make a different default for each while making that default low priority so that other things override it? Or should they be one enum, with a "default" option that uses different option for each of friction and restitution, leading to good behavior by default, but allowing overriding it in the same order of precedence? |
What happens to the tweaks when a user reimports a gltf? Material mixing is somewhat arbitrary and based on heuristics. Real material interactions are always unique to the surface pair. If you want to fully generalize material property combinations, I would give each surface an identifier. Then I would have a lookup table based on surface pairs. This could be fairly fast at runtime with a hash table. This is a bit tedious to author because the user needs to fill out a material matrix. That matrix could having mixing rules instead of material values. The default mixing rules could be used if a matrix entry is missing. |
Whether you use an inherited scene, editable children, or an import setting, the tweaks should be kept.
Correct, these material properties are most accurately described as the interaction between two surfaces. However, for practical reasons, this won't be done. It's not really reasonable to expect users or content creators to make such complex tables, it doesn't work with asset imports bringing in new materials (even ignoring glTF, copying a Godot scene from one project to another can have this problem), and this is different from what every other game engine does. |
It may not be reasonable to do this in gltf, but this sort of thing already exists in Unity with their layer system. Some engines also have tables like this for VFX and SFX. For example, what sound should metal hitting felt play? |
@erincatto This is a bit off-topic but I want to mention that there is an effort to standardize the acoustic properties of materials use them for calculating effects. A prototype made in Godot is available here: https://github.com/Straven35/godot-spatial-audio |
Describe the project you are working on
I am working on glTF import and export in Godot, allowing people to make objects in Godot and export them to glTF for use in any engine, or make objects in any engine and import them into Godot.
Describe the problem or limitation you are having in your project
https://docs.godotengine.org/en/stable/classes/class_physicsmaterial.html
The problem is that Godot's PhysicsMaterial class has combine modes that do not behave like any other game engine.
For friction, Godot has a a
rough
boolean. If true for both, uses the highest rough one (maximum). If false for both, uses the lowest friction (minimum).For bounciness/restitution, Godot has an
absorbent
boolean. If true, it subtracts the bounciness from the colliding object's bounciness. If false, they are added together.This is different from everything else I've seen.
sqrt(a*b)
) for friction, and only the maximum for restitution. https://defold.com/manuals/physics-objects/#collision-object-propertiesContactConstraintManager::CombineFunction
callback function. https://jrouwe.github.io/JoltPhysics/class_contact_constraint_manager.htmlDescribe the feature / enhancement and how it helps to overcome the problem or limitation
The proposal is to add more options for friction and bounce combine modes.
First and foremost, both of these booleans should be replaced with enums. It is clear that there are more than 2 ways to do this, and Godot's choice seems arbitrary. We can do this without breaking compatibility by keeping the booleans around as wrappers for the underlying enums.
The important discussion here is what should be the allowed values of the enum. We may want to go with an extensive list, since this should be trivially easy to implement, especially in Jolt where we can provide any callback function.
Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams
In a 4.x update, change the underlying data structure for the combine modes to be an enum. Expose this enum, and keep the existing booleans as wrappers for the existing behavior. If the default value of each combine mode is equivalent to its existing behavior, then compatibility is not broken (almost, the behavior of "rough" when one is rough but low is a bit unusual...). The enum could look something like this:
Or maybe like this, to have the first 4's precedence behavior the same as Unity/Rapier/Bevy (and possibly others, most don't specify):
We should get feedback from physics experts before going with this, especially with the ordering of the enum, because I really don't know what's best there, and different engines seem to disagree on what takes priority. Also, I'm really unsure about "default" being a thing.
However, as a general note, I don't see any downside to having the list of available options be quite extensive. They should all be very easy to implement, and having so many allows Godot's physics to behave like physics in any other engine, which is cool, and makes Godot very flexible.
In the next compatibility breakage, 5.0, the boolean wrappers could be removed. Also in 5.0, we could change the default values of these enums to something that makes more physical sense. But this is not required to implement this feature.
If this enhancement will not be used often, can it be worked around with a few lines of script?
No, physics is a core feature and working around its limitations is not really possible unless you modify the engine.
Is there a reason why this should be core and not an add-on in the asset library?
Physics is a core feature, and glTF import/export is a core feature.
The text was updated successfully, but these errors were encountered: