Skip to content
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

RigidBody freezes in rotating Spatial #45268

Open
Tracked by #45333
ngreve opened this issue Jan 17, 2021 · 16 comments
Open
Tracked by #45333

RigidBody freezes in rotating Spatial #45268

ngreve opened this issue Jan 17, 2021 · 16 comments

Comments

@ngreve
Copy link

ngreve commented Jan 17, 2021

Godot version:

v3.2.4.beta.custom_build.e25984a74
Commit: d59414051b

OS/device including version:

OS: Arch Linux
Backend: GLES3

Issue description:

What happens:
When putting a RigidBody with mode Rigid into a Spatial node which is rotating, the RigidBody physics seems to freeze/break.

What was expected:
I expected that all physics happens to the local parent Spatial orientation. Especially when combined with a gravitational field, which is demonstrated in the video.

Steps to reproduce:
The video shows how I (try to) bounce with the player against the box during different stages.

The sphere represents a planet, which is a RigidBody in static mode.
The box is a RigidBody in rigid mode, which is affected by a gravitational field.
Both are children of the RotationSpatial which exports the variable Rotation Enabled which starts or stops the rotation.
In short:

  • Rotation on -> box freezes
  • Rotation off -> box works again
rotation-2021-01-18_00.37.15.mp4

Minimal reproduction project:

Project captures mouse pointer, which can be freed by pressing ESC. Clicking into the window, captures it again.

Project: rotation.zip

@Calinou
Copy link
Member

Calinou commented Jan 18, 2021

cc @pouleyKetchoupp

@slapin
Copy link
Contributor

slapin commented Jan 18, 2021

It is not expected by RigidBody to inherit Spatial rotation due to the fact that RigidBody exists in physics world at top level and is controlled by physics engine. If you want to rotate RigidBody, just apply torue.

@ngreve
Copy link
Author

ngreve commented Jan 18, 2021

I am trying to implement a space environment. So the goal is, that objects on the planet, follow the rotation of the planets surface. That's why the box and the planet are in one Spatial. The spatial is used to simulate the rotation of the planet.

add_torque() would rotate the RigidBody around its own origin, not around the planet's center. (Or am I missing something?)

@slapin
Copy link
Contributor

slapin commented Jan 18, 2021 via email

@ngreve
Copy link
Author

ngreve commented Jan 18, 2021

I could do that, but it would somewhat question the whole use of the scene tree concept, if child nodes can unexpectedly behave different, when they are children of a spatial.

I do not expect the children do be affected by the parents movement on a physics based level.
E.g. forget the rotation for a moment. Imagine the following scene:

-WorldNode
  |- ShakingSpatial
    |- RigidBody

When I now would shake the ShakingSpatial, I would not expect the RigidBody to build up momentum relative to the WorldNode and fly around. I would expect the RigidBody to simply follow the translation of the ShakingSpatial and behave physically correct within and relative to the the ShakingSpatial. The ShakingSpatial would be, in some way, its own inertial frame of reference for all its children.

Back to the rotation example of this issue: I would not expect the box to build up centrifugal force. The box should simply follow the translation like any other static object plus the translation caused by collisions from within the RotatingSpatial.

For further clarification of my problem: Thanks for your advice so far, but I am less in search of an alternative solution. "Calculate it yourself" is almost every time a solution. At this point my question is more like if this is officially expected behavior or not?

@pouleyKetchoupp
Copy link
Contributor

I can confirm this is the expected behavior.

The logic behind it is:

  • The physics simulation happens in the world and controls rigid body positions by default.
  • If you directly change a rigid body position through its transform, or indirectly by moving its parent, you're actually teleporting the object in the physics simulation. If you do it every frame, it looks like the object's physics simulation is freezing.

I would expect the RigidBody to simply follow the translation of the ShakingSpatial and behave physically correct within and relative to the the ShakingSpatial. The ShakingSpatial would be, in some way, its own inertial frame of reference for all its children.

That would require the ShakingSpatial to have its own physics world, separated from the default frame of reference. Right now this use case is not possible out of the box, because separate worlds can be setup only in the context of a Viewport. Also that would mean rigid bodies within different worlds wouldn't interact with each other.

In the use case from your original example (planets) the proper way is what @slapin exlplained, using a script for custom physics (although Area space override can help for things like local gravity).

I'm closing this ticket since the original issue is addressed, but feel free to re-open if I'm overlooking something.

@ngreve
Copy link
Author

ngreve commented Jan 18, 2021

Quick hack to show the kind of procedure I had in mind.

Script attached to RigidBody:

extends RigidBody

var last_state:PhysicsDirectBodyState
func _integrate_forces(state:PhysicsDirectBodyState):
	last_state = state

func _physics_process(delta):
	if (!last_state):
		return
	
	translate(last_state.linear_velocity * delta)
	rotation += last_state.angular_velocity * delta

This already results in (rotation speed increased):

rotation-quick-hack.mp4

Obviously buggy, but one can see where this is going.
I would expect this to work way better, if this kind of "algorithm" is used in the core engine.

But ok, I will figure it out eventually.

@Zireael07
Copy link
Contributor

Is the issue (Rigidbody not inheriting Spatial rotation) made clear in docs? I don't think it is, as I had an extremely similar issue with carting around Rigidbody items in my FPS tech demo...

@pouleyKetchoupp
Copy link
Contributor

Is the issue (Rigidbody not inheriting Spatial rotation) made clear in docs? I don't think it is, as I had an extremely similar issue with carting around Rigidbody items in my FPS tech demo...

Ok, makes sense. Let's make sure the documentation states very clearly how rigid body transformation works.

@slapin
Copy link
Contributor

slapin commented Jan 19, 2021 via email

@ngreve
Copy link
Author

ngreve commented Jan 20, 2021

Just a note: This type of issue will probably also be a problem for anyone who tries to use the (continuous) floating-origin approach, which is is very common way to render real planetary scale environments (typically in space games).

And no bad intentions, just want you to know that I've built the scenario from the issue in Unity and it works as expected there.

@slapin
Copy link
Contributor

slapin commented Jan 20, 2021

Need to mention that Unity has entirely different approach to objects due to composition system as Godot has OOP system with Spatial being entirely different beast from PhysicsBody. You can't mix things like that. If you want to shift origins you have to move all physics objects in manner without momentum accumulation i.e. by storing and recovering linear and angular velocities in the same frame. Anyway, constant conversion of transforms from local to global space and back to keep hierarchy is too expensive to be worth it. It is always better to solve problems in more dedicated ways. I think just making origin shift helper would solve problem like this.

@ngreve
Copy link
Author

ngreve commented Jan 20, 2021

You can't mix things like that.

This was a comparison from the viewpoint of an engine user, not an engine developer. I would say that game devs simply choose the engine where stuff works, and when they find issues like that, they will take a look at other engines, how they handle their game idea... especially during prototyping and when they had considered to switch to Godot. Again, this was not meant as a "gotcha". Maybe I will try to take a look into Godots source, to come up with my own solution, even though this could take a while.

And back to converting the necessary motion into forces: I doubt that this will work on the long run, because of floating-point error accumulation. This is in turn, would sooner or later result in random movement/jiggling of the RigidBody, because the error-prone calculation will result in overlapping collision bodies. But when precision is not a problem for someones game, of course this could work. Furthermore this approach makes the sleep mechanic obsolete (if someone cares). As the documentation says about sleeping rigid bodies:

This saves an enormous amount of processor time when there are plenty of rigid bodies

There are some other things, I think will be problematic, but in the end, testing is above studying.

@Zireael07
Copy link
Contributor

@ngreve: For my fps game, I solved the problem by manually setting the rigidbody's position and rotation while carried. I am not sure it will work for you because this requires physics to be disabled on the rigidbody being carried (collision shape disabled and/or setting the item to sleeping)

Is there a particular reason you need to have the box be a rigidbody? At galactic scales, you could just as well lerp and set position/rotation manually and use areas for collision/click detection.

@ngreve
Copy link
Author

ngreve commented Jan 20, 2021

Is there a particular reason you need to have the box be a rigidbody?

This was simply because of the need of a minimal project for this issue. At this stage I cannot clearly say what kind, how many or at which scale my rigid bodies will be. I am currently just prototyping the main mechanics, as the idea grows. But thanks for the hint, I will consider it, if it fits.

@ngreve
Copy link
Author

ngreve commented Jan 21, 2021

I tested it with Godot 4 and I have some interesting news.
In the beginning it's a bit laggy because my laptop is complete garbage and it seems to have problems with Vulkan in general.

rotation-godot-4.mp4

Nonetheless it seems to work as expected in the first place.
(The outer smaller sphere is just to visualize the rotation, because Godot crashes on my machine when I try to apply a shader)

The Capsule is a static rigid body and is not a child of the rotating Node3D.

Godot: 4.0.dev
Commit: a9b151c
Project: godot_4_test_proj.zip

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants