-
-
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
Improve and harmonize API for forces in RigidDynamicBody2D and RigidDynamicBody3D #3601
Comments
This has been switched in 4.0 for consistency so that the force/impulse value comes first: godotengine/godot#37350
Why have |
Thanks, I've just edited the proposal to take this change into account.
The property is still useful for extra cases, like checking the total applied (including torque created by a force with offset) and clearing forces. I was thinking about adding |
I think this is a good compromise. I’m assuming this means the 2D physics engine will need to clear the internal |
Yes, indeed. 2D and 3D will need to handle both forces that get cleared and constant forces that don't. |
I'm not convinced that the arguments:
justify adding a third set of methods:
Addressing each argument individually:
A one-shot force is an impulse, which can be applied directly using
With godotengine/godot#42850 this would simply require a single line of code: Note: This is how it works in 2D at the moment! godotengine/godot#42850 is simply making 3D the same as 2D. It's just making them consistent. It's not introducing anything new. As per the best practices, we need one solution for each problem. We should not have multiple methods doing the same thing. |
Why should I have to manually clear out the force each frame to apply this force? Going back to the thruster example: why is
better than just
The vast majority of the time someone would want to apply a continuous force, it's dependent on an ever changing direction (ship direction, direction from object a to object b, etc). It doesn't make any sense to make the default behavior apply the force in single unchanging direction forever. It's just adding an extra step to the behavior for no reason. While you can achieve this behavior using The other problem with requiring a user to manually clear |
@atinymelon I apologize if I'm missing something, but what exactly is the problem with using |
@aaronfranke It's mostly a naming issue. Calling |
With godotengine/godot#42850 you can also do:
or
or
They're equivalent and the choice is up to the user and depends on the circumstances. |
None of these really work for a situation where other nodes are applying forces to a body, because the affected body needs to ensure its For reference, the reason many physics engines accumulate forces into a temp field like This is one major reason why using |
Whether or not using As per the best practices, there needs to be a problem before providing a solution. Do you have a practical example that demonstrates the problem with using |
Well the actual problem we're trying to solve is that 2D and 3D physics are inconsistent in their behavior. I'm arguing that clearing the 2D forces as in godotengine/godot#38648 is the better option than not clearing the 3D forces as in godotengine/godot#42850, because clearing the forces results in a simpler and more intuitive API. What practical benefit is there to not clearing the forces and requiring the user to manually clear it themselves? |
As stated previously: This is the expected behaviour when using standard event driven programming. For example, enabling a thruster when a key is pressed and disabling it when it is released.
This is my previous comment: If the user uses the
godotengine/godot#42850 is the better option, because, as stated in the OP: Currently, in 3D, the only difference between
godotengine/godot#42850 makes 3D physics consistent with 2D physics and the documentation. It ensures that |
Just to reiterate on the two problems we're trying to solve here:
The second problem is about usability and goes a little bit beyond mathematical or physical justifications. Applying an impulse and applying a force is not equivalent, and the API should reflect that to be as clear as possible. The proposed solution here is to use 3 sets of functions to make it perfectly clear: I'm interested in having a discussion about alternative solutions to this second problem, but it doesn't make a lot of sense to try and force the discussion into going back to the state of a PR that had a majority of votes against it. |
The way I see it, there are four options:
The option selected should be the best option for Godot users. In my opinion this is option 2: Make 3D the same as 2D. It provides the simplest API with all the functionality. |
I've opened godotengine/godot#55736 to implement the solution from this proposal that appears to gather the most consensus. This PR also improves the documentation to alleviate any possible confusion with the different methods. |
I'm not convinced there is a clear understanding of what is meant by a consensus.
It is definitely not about finding the most popular option. My understanding is that it's about debating the pros and cons until there is no more sustained opposition. |
Describe the project you are working on
Godot Engine
Describe the problem or limitation you are having in your project
Following up from godotengine/godot#42850 (comment).
The current problem is that
add_force
and equivalent functions have a different meaning in 2D and 3D:In 2D, they add constant forces that keep being applied over time.
In 3D, they add one-shot forces so you need to call them every frame.
On the other hand,
apply_impulse
and equivalent functions are always applied only once in 2D and 3D.In the linked PR, the proposed solution is to modify the 3D implementation to do the same thing as in 2D, so forces are always applied over time whereas impulses are one-shot.
This generally makes sense from a physical point of view, and makes some simple cases very easy, like setting a constant thruster force on and off.
On the other hand, it can make it cumbersome in some use cases:
-Applying one-shot forces wouldn't be possible directly anymore, it would require using impulses with a
* delta
factor which can be difficult to understand for users not familiar with physics systems.-When multiple forces need to be set on and off, it would require to clear all forces and re-apply the desired ones.
Describe the feature / enhancement and how it helps to overcome the problem or limitation
This proposal aims at finding a compromise for an API that allows these use cases to be doable and easy for beginners.
The general idea is to propose two sets of functions for forces and torques:
-
apply_force
and variants can be used for one-shot forces, like the equivalentapply_impulse
functions-
add_constant_force
and variants can be used for forces that keep being applied over timeDescribe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams
Here's the full API for forces, torques and impulses for 2D (the equivalent will be done for 3D):
Functions:
void apply_central_impulse ( Vector2 impulse )
Applies a one-time impulse at the body's center of mass. It's time independent and meant to be used for one-time events.
void apply_impulse ( Vector2 impulse, Vector2 offset )
Applies a one-time impulse at the given local position. It's time independent and meant to be used for one-time events.
void apply_torque_impulse ( float torque )
Applies a one-time torque impulse. It's time independent and meant to be used for one-time events.
void apply_central_force ( Vector2 force )
Adds a one-time force at the body's center of mass. It's time dependent and meant to be applied every frame.
void apply_force ( Vector2 force, Vector2 offset )
Adds a one-time force at the given local position. It's time dependent and meant to be applied every frame.
void apply_torque ( float torque )
Adds a one-time torque. It's time dependent and meant to be applied every frame.
void add_constant_central_force ( Vector2 force )
Adds a constant force at the body's center of mass that keeps being applied over time.
void add_constant_force ( Vector2 force, Vector2 offset )
Adds a constant force at the given local position that keeps being applied over time.
void add_constant_torque ( float torque )
Adds a constant torque that keeps being applied over time.
Properties:
Vector2 constant_force
The body's total applied constant force. Can be used to clear all constant forces with
constant_force = Vector2()
.(in 2D, this was previously named
applied_force
but this new name seems less ambiguous given the API)float constant_torque
The body's total applied constant torque. Can be used to clear all constant torques with
constant_torque = 0.0
.(in 2D, this was previously named
applied_torque
but this new name seems less ambiguous given the API)If this enhancement will not be used often, can it be worked around with a few lines of script?
The harmonization between 2D and 3D has to take place in the core engine.
Some parts of the API could be worked around by script, but they would involve some knowledge in general physics properties, so a more complete API is needed for extended usability.
Is there a reason why this should be core and not an add-on in the asset library?
This is core because it changes basic functionalities of core nodes.
The text was updated successfully, but these errors were encountered: