Rigid Bodies as hands

Godot Version

4.2.2

Question

Just started using OpenXR and was wondering how to replace the hands with rigid bodies that can interact with the environment. Having them as a child of each XRcontroller doesn’t seem to work, and I have no clue how to get the position and rotation of the controllers to possibly map a rigid body onto them.

Thanks for the help guys

This is not a simple thing, so lets start with the three things that are the TLDR and then go into some detail.

  1. When you add a RigidBody as a child, you have to keep in mind that the parent node, isn’t governing the movement of the RigidBody. That is controlled by the physics engine which will enact gravity on it, making the rigidbody just fall down. Yes the parent moving will have an effect, but mostly the effect will be the physics engine fighting against that movement.

  2. You get the position of the hands simply by accessing the global_transform on the XRController3D node. There are more complex ways to get to the internal data directly, but just reading out the transform on the controller node is easiest.

  3. Godot XR tools has an implementation that you can look at: godot-xr-tools/addons/godot-xr-tools/hands/scenes/collision at master · GodotVR/godot-xr-tools · GitHub
    These nodes can be added as a child of the XRController3D node and they will be positioned correctly keeping collisions in mind. There are some demos in XR tools that show how it works.

Then for the longer answer, there are a couple of problems we’re dealing with here. The main one is that as you move your hand, and the tracking systems updates the position of the node, that change of position happens outside of physics. It’s akin to teleporting from the old location to the new location. You are not actually moving the node along a path checking for collisions, no if you child a physics body to your hand, you’re just teleporting it inside the wall and the physics engine panics.

So the way to approach this is that you need a physics node that follows the hand around and properly checks for collisions along that path. In the XR tools example we do this by childing a physics body to the hand but setting the property top_level to true. This means that the parent is ignored when positioning this node. Now we can move this node from it’s current location, to the location of its parent.

How this is implemented than differs from the type of physics body you use and so far people are still experimenting with the different options and trying to find out which works best.

My experience is as follows:

  1. You can use a RigidBody3D node and at face value that seems to be the best choice as it does all the right things collision wise. But there is no mechanism to tell it to move to a new location. The best way I’ve found is to implement a custom integrator that performs the follow logic. That works pretty decent but I have found it can do weird things on certain collisions.

  2. You can use a CharacterBody3D node and this gives you access to move_and_collide and move_and_slide as methods to move. This works recently well from a POV of stopping the hand from going through walls and tables, but I’ve found the interaction with RigidBodies to be immensely unstable, even being able to push objects through floors. Also the collisions are one directional, which is a problem.

  3. Finally, what we do in XR Tools, is use AnimatableBody3D and then use move_and_collide to implement our own collision code and apply forces to any RigidBody3D we collide with. This has by far proven the most stable, but we lack the ability to properly handle collisions while rotating the hand.

All in all, my conclusion at this moment is that the physics engine in Godot, and to the best of my knowledge many other physics engines, lack the ability to do this perfectly and it’s always a best effort.

One last thing, I have heard others have had success using SpringArm3D or roll their own raycast based solution. But I have no examples to point at here.

Wow, thank you so much for the very detailed reply. I did try getting a characterbody 3D and a rigid body to follow the hand at some point, but I wasn’t able to get it to work right. I will keep trying though and I’ll definitely try an AnimatableBody3D as well. At the moment I’m trying to figure out a proof of concept for a game, but I still have a lot of learning to do about godot 3D and VR.
Thanks again

1 Like

AnimatedableBody3D is great for simple shapes. The XR Toolkit has a physics version of it’s hands you can use, though I have had no success de-activating them when need be.

So I’ve worked on implementing both RigidBodies and AnimatableBody3D, I could get both to follow the controllers, but I ran into a few problems.

  1. I was using apply_torque to get the rotation of the rigid bodies to follow the rotation of the controller, and that worked but it didn’t like it when the controllers pointing towards me and it would spasm whenever I did that.
  2. Animatable bodies seem to follow the hands well using move_and_collide, but they have very little force when pushing other rigid bodies. I tried increasing the following speed but when I did that past a certain point it gave up and started randomly floating
  3. Animatable bodies also for some reason don’t want to rotate and move at the same time. Apparently a fix for this is adding a parent node3d and transforming that but you can’t call move_and_collide on that

I apologize if these seem like simple fixes, I wasn’t able to find resources anywhere else on fixing them.

Huh, I put my AnimatableBody3D directly as a child of the XR Controller and it worked, only unchecked the “Sync to Physics” box. No script interference outside of disabling them by changing the collision mask

:sob: no way this really works. It just goes through static bodies but for what I’m doing that’s completely fine. Thanks a lot

1 Like

Right I forgot about static bodies! My game also does not mind hand-thru-walls but it would be nice to find a solution to such.

unfortunately this does bring another problem. Because the animatable body is directly on the controller I have infinite strength. I assume the only way to fix this is with the previous method of having the body follow the controller so I may have to use that again. :upside_down_face:

Infinite strength, and if you move your hands fast enough, the physics engine stops making good choices because it has no velocity information.

So by trying you’re finding out the reasons why you need a physics object that follows, and what other issues come round.

Full physics interactions with hands with all bells and whistles is difficult, not just in Godot but any game engine. So my advise is, start small, start with the basics.

Hopefully as more and more people experiment with this stuff, the more likely good toolkits come out that give you a head start.

1 Like

I appreciate the reply. I’ll keep trying and learning about this. Do you mind helping me with the above problem?

I can get the animatablebody3D to follow the controller easily, but when I try to multiply the follow velocity of the animatablebody3D so it has more pushing force, it starts overshooting the location of the controller and begins to float in the air. Or it may not really be overshooting, I have no clue what it’s doing

When I try to get a rigid body to follow the controller instead, I run into problems with rotation. I try to get the rotation of the rigid body to follow the rotation of the controller using apply_torque, but for some reason when the controller is in certain angles on the y and z axes the rigid body just begins to spin really fast.

I’m curious if there are solutions to these problems, or maybe my methods are flawed. Thanks for all the work you do for XR

What we do is not let the animatablebody do the pushing, we move it until it detects a collision, then if that object is a rigidbody then depending on the velocity of the hand, and some of the collision info, we exert a force on that object.

what about angular velocities of the hand? How would you calculate how those affect the object. Also what if the rigid body is already moving but the hand is stationary so it has no velocity. If I did solve these it seems like it’d be doing the same thing as the built in physics engine no?

These are things I’m planning to dive into in the near future. So far the solutions I have don’t properly deal with those.

1 Like