-
-
Notifications
You must be signed in to change notification settings - Fork 21.7k
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
Give each RigidBody its own DirectBodyState wrapper. #42928
Conversation
Rebased following merge of #42167. |
Allow the user to store this pointer is unsafe. The pointer lifetime is totally handled by the On the other hand, with the removal of the multi-thread sync mechanism, the existence of this |
The same can be said of any variable pointing to any object. However, it's just a wrapper so its memory requirements are tiny (the pointer) compared to the underlying
This is beyond the scope of this PR, would be compat breaking, and would probably need to be discussed in a proposal first. This PR simply address issue #42877. However, bear in mind that there is still a requirement to prevent access to the underlying PhysicsServer during the physics step even if this is not needed in a single threaded environment. |
Though, an object whom lifetime depends on the lifetime of another object, related for sure but not so much code wise. The API was not designed to work like this; it should never be stored. Also, Considering that this PR is changing the API behaviour and the physics engine sync mechanism was removed without a proposal, my idea was to simplify it further so to keep it more safe (and for sure less annoying to use); but if you feel like that the time taken to change it doesn't worth the result, feel free to merge it. |
+1 for this |
iterations = 8; // 8? | ||
stepper = memnew(Step2DSW); | ||
direct_state = memnew(PhysicsDirectBodyState2DSW); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel it may be a better idea to create this on demand (when requested, if null, create and return)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is used to sync the server state with the Godot scene every iteration; so I think there is little point in delaying its creation:
godot/servers/physics_2d/body_2d_sw.cpp
Lines 586 to 592 in a5fa919
void Body2DSW::call_queries() { | |
if (fi_callback) { | |
PhysicsDirectBodyState2DSW *dbs = PhysicsDirectBodyState2DSW::singleton; | |
dbs->body = this; | |
Variant v = dbs; | |
const Variant *vp[2] = { &v, &fi_callback->callback_udata }; |
BTW This PR simplifies this to simply use it's own copy:
![DirectAccess](https://user-images.githubusercontent.com/9253928/100980049-93dd5d00-353c-11eb-9b30-ce7e534cf50d.png)
Note: fi_callback
is defined during the RigidBody
creation:
godot/scene/2d/physics_body_2d.cpp
Line 863 in a5fa919
PhysicsServer2D::get_singleton()->body_set_force_integration_callback(get_rid(), this, "_direct_state_changed"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
anecdotally, I just pulled this into our fork and it's great. To the point that we're just going to use the direct state for everything before we step our physics spaces. |
And just a comment and maybe something to note/consider: @reduz why is it explicitly the physics server's job to wakeup() a body after applying force, impulse, setting velocities, etc? Can't the body wake itself up within it's modifier function? For example, this is how it's done in Box2d: b2Body flags itself awake when modifier function is called. There's no need for another object to know about this detail.. Just something to consider. When we apply_impulse or set_linear_velocity manually on the direct state, we now (as did the physics server) have to explicitly wake the body up in direct state as well... More bookeeping. IMO the physics body can compare the incoming parameter and decide if it should wake itself up or not.. |
direct_state->body = body; | ||
return direct_state; | ||
ERR_FAIL_COND_V_MSG(!body, nullptr, "Body with RID " + itos(p_body.get_id()) + " not owned by this server."); | ||
ERR_FAIL_COND_V_MSG((using_threads && !doing_sync) || (body->get_space() && body->get_space()->is_locked()), nullptr, "Body state is inaccessible right now, wait for iteration or physics process notification."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also think this handles multi-threaded nicely. i.e. if someone uses this incorrectly they will know.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change looks good to me, it's a nice fix to have and doesn't break compatibility.
I agree with what was said before about simplification: we could probably remove the direct body state completely and handle state changes in the rigid body node directly, but that would require a separate proposal/PR.
Update from discussing this PR on IRC with @reduz:
So I guess for now #42929 could be merged? |
@pouleyKetchoupp Pretty disappointing to hear this will not be merged in 4.0. Can the discussion be shared so others can get up to speed on the removal for the proposed better way? |
@jordo The summary of the discussion is: -The only point of the direct access is that it protects the object at a very specific point in time which is the direct state callback and gives you access to the node internals. -The proper fix is making the threading in the physics servers work properly, @reduz will work on rendering soon, so he can work on the physics side at the same time. -Once this is done, DirectBodyState can be removed and be replaced with a callback (C++ Callback for C++ and a Callable if you supply one). |
If it's going to be merged into 3.2 it should be merged into master first. Arguing that it will be removed later as a reason not to merge it into master, doesn't make sense, because there is no guarantee that it will be removed before 4.0 is released. Even if there was already another PR that removed it, until that PR is merged, and hence supersedes this one, there is no reason not to merge this one into master first. |
Rebased following merge of #45519. |
With #49471 merged, I believe there is not much of a point in directly accessing the body state as this is only a way to pass the state from physics server to the node faster. For most cases, accessing via server is enough and its safer. If something is missing there, it can be changed. As such, I will be closing this. |
Currently 2D and 3D, Godot and Bullet physics servers have a singleton wrapper for
DirectBodyState
. This means that only oneRigidBody
'sDirectBodyState
can be accessed at any one time. This is an unnecessary and cumbersome restriction that is not thread safe. Aside from also being used to store the current step size, it's just a wrapper, so I can see no reason why this should be a singleton.This PR gives each
RigidBody
its ownDirectBodyState
wrapper and moves the current step size toSpace
, where it belongs and already done in Bullet.Fixes #42877.