Godot Version
4.2.1
Question
What I am basically trying to do is keep the inertia of a RigidBody3D constant despite adding or removing collision shapes (add_child, remove_child).
I found that I can set a custom inertia manually in the editor. When I do this, the inertia does not update on changing collision shapes, so this would do the trick. But it would be a lot of effort to set many RigidBodies to correct values manually.
All methods to set the inertia in code seem to do nothing, no matter if I the editor’s custom inertia is 0 (“auto mode”) or already set to a value.
What I tried is:
set_inertia(base_inertia)
inertia = base_inertia
PhysicsServer3D.body_set_param(self, PhysicsServer3D.BODY_PARAM_INERTIA, base_inertia)
RigidBody3D also has a method set_custom_inertia()
, which takes zero arguments, is not documented and also seems to do nothing.
An alternative solution to my problem would be to have collision shapes that detect collisions, but do not contribute to the inertia calculation. However this does not seem to be possible either.
I know that it is possible to completely replace the physics calculation, but I am not a physics major and this method also appears to be overkill for solving such a simple problem.
Collision shapes will not modify the physics body they are just shapes to detect collisions.
Also the set_body_param’s first parameter is an RID, “self” is not an RID.
Lastly Godot strangely associates inertia with rotation physics only. It sounds like you want to just adjust the mass for whatever is added or removed.
Thanks for your answer.
Collision shapes will not modify the physics body they are just shapes to detect collisions.
Unfortunately they do. I have tested this repeatedly.
Also the set_body_param’s first parameter is an RID, “self” is not an RID.
That is a good point. It appers like RidigBody3D and CollisionShape3D nodes don’t have a RID.
But I can get the RID for the “shape” inside the CollisionShape3D node. I tried to set this shape’s inertia to 0,0,0 using the PhysicsServer and THEN add/remove the CollisionShape3D to/from the RidigBody3D. Unfortunately this still changes the inertia of the Rigidbody.
Lastly Godot strangely associates inertia with rotation physics only. It sounds like you want to just adjust the mass for whatever is added or removed.
As far as I understand it, the total mass is just the value that one enters into the “mass” field of the RigidBody3D. Then the collision shapes are used to calculate the distribution of this mass within the body for calculating center of mass and rotational inertia.
That makes sense when it’s put like that, I thought you were not a physics major
.
Have you tried:
PhysicsServer3D.body_reset_mass_properties(RID)
I assume the rigidbody caches the calculations and doesn’t listen for child changes regarding shape. This should recalculate the mass based on it’s “shape”, or shapes.
Changes apply immediately. When I add or remove a shape, the inertia changes instantly. PhysicsServer3D.body_reset_mass_properties(RID)
does not change anything, it probably just triggers re-calculating the values, but as the inertia is already current, the new result is the same again.
Just to confirm the behavior (and also to confirm that collision shapes and shapes for inertia-calculation are the same), when I call PhysicsServer3D.body_clear_shapes(self)
, the inertia immediately resets to (1, 1, 1)
and my rigid body can’t collide with anything any more.
An yes, I used self
instead of a RID
. Curiously this works - it worked the whole time, I just didn’t notice.
I have given up on the inertia-problem for now. I have replaced my sophisticated collision shapes with a single one and hope that nobody will notice that I am cheating. I may revisit this topic some time in the future.