• 3D
  • Holding a Rigidbody object

For my project I'm working on a system that the player can grab a physics object akin to Half-Life 2, Soma, ... I thought a lot about it and experimented with various popular methods of picking up and holding an object so that it interacts with the world in a nice fashion. One method I tired was parenting the object to the camera so it follows the camera around, but that method resulted in very unexpected physics and collision behavior. I tried updating the position of the picked up object every physics frame to be in-front of the camera. I even believe that's how it was done in half-life 2. I also tried freezing the rigidbody object and moving it around by manually setting the linear velocity. However all of these methods resulted in several problems with collision and interaction with other geometries and physics bodies. It was not a robust and modern framework to build upon. However, I discovered a fairly good method of achieving such system and that's with the help of Joints. This setup has several advantages compared to the former/popularly used methods. This method is very easy to set up and configure. It also has a great performance advantage as it does not require to run a piece of code every frame! It is very robust and flexible. Here is the basic (camera) node setup: The static body acts as the hinge where the object will be grabbed from. It doesn't need to have a mesh and or collision. In my case its fully empty. The joint itself is a Generic6DOFJoint with almost default settings. The static body is set as Node A in the Nodes section. Node B will be left empty and will be assigned via code. This is how I've done it:

var picked_object = get_collider().get_path()
physics_joint.set_node_b(picked_object)

After executing this code, the object at the end of the raycast will automatically get pinned to the defined position and that's it! Not only this setup performs better than the formerly mentioned methods but also it reacts to external rigidbodies, forces, and collisions in a much more convincing way.

However, I'm having some trouble finalizing this setup. The biggest problem is when looking at a wall or the floor, it's easy to crush the object into a collision shape, making the physics system freak out. Essentially when looking at a wall up-close, the held object should be pushed closer to the player's face. I thought of moving the Joint position to the end of a raycast node casting from the player camera, but the problem with it is that, the picked up object is being moved around by its origin point and because of the size of the object it will result in half of the object still being crushed into a wall. Also if it gets too close to the player, it will crush into the player and will push the player in some direction.

I'm asking the community for help and for ideas on how to overcome these issues and finalize this into a setup that could be used in other projects as well. How do you think it's possible to control the position and physics handling of the picked up object so that it won't crush into the wall and the player?

Probably above my paygrade, did you create the player as a complicated rigid body or a "simpler" kinematic body? I think there are collision layers/masks that can help with this, you could perhaps put your player into a different layer as the object behind held? Just temporarily.

@Erich_L said: did you create the player as a complicated rigid body or a "simpler" kinematic body?

At the moment the player is a Kinematic body. But this is part a project that I'm working on, to make an advanced and fully viable physics driven player character. I plan to release it as a free and open-source framework.

I think there are collision layers/masks that can help with this, you could perhaps put your player into a different layer as the object behind held? Just temporarily.

Yeah that would solve the problem of the object getting jammed into the player. However, there is still the issue of the held object being jammed into walls and other objects.

It hit me out of nowhere that if the joint can be 'broken', it might solve the issue to some degree. I don't think that the Joints themselves have a breaking feature. But it might be possible to implement this via GDscript. Something like, if too much force is being applied to the held object, it simply drops. But that could introduce some new problems like the player having buttery fingers :D as everything falls from their hand with even slight collisions and also the fact that this would require a code to run every frame which defeats the point of this setup.

I experimented with such a feature a couple months ago.

The rig setup i have now is a kinematic rig controlling a rigid body character. The rig uses 6dof (actually two) with spring relations and linear limits to pilot the actual (capsule!) character body. Tweaking the spring params to your satisfaction may take a little time to gain a good intuition on how the (spring) params interplay. Absolutely consider linear limits to prevent the spring restoration force from growing too large

You may wish to implement a limiting factor on the rig (kinematic body) forcing/force application on rigid body it controls to limit the forces it may apply. For example: if the rig is some distance from the controlled object, user inputs no longer effect it and the rig is instead drawn towards the controlled object. If you are developing a frame work you might want to provide signals for this condition for UX feed back.

You should also consider using area/ray cast on the camera to get sense of its approach to scene objects because driving a camera into scenery is visually unpleasant anyway.

I prefer using spring relation on any kinematic driving a rigid-body when target bodies interact with the environment generally

In general the rig I have itself is an instance of your desired behavior because it is a kinematic body directly manipulating (an assembly of) rigid bodies via 6dof joints.

I would not recommend using a static body being moved around. Static bodies are modeled as -static- in the (Bullet) physics engine. Use a kinematic body instead which is expected to be under programmatic control.

Generally futzing with the physics simulation by injecting velocities is touchy because you can overwhelm the modeling or conflict its forward estimations and collision modeling.

Thank you for the advice @dotted but that's not what I am doing at the moment. I'm trying to create an object pickup system akin to the one in this video:

I'm trying to create an improved version of this system using joints.

Joints should work. I found 6DOF Joint to be buggy and not work well (also listed as deprecated) so I used a simple Pin Joint and it seemed to work okay. You'd also have to limit the axis (lock) so it doesn't spin around wildly. But should be fine for simple HL2 style pickups.

Right I pick up objects and carry them around half-life like except nicer. That is what the kinematic rig does it fluidly controls a rigid body character. Half life pickups and carries were quirky some times very irritating and perhaps intended to look like that but I feel like the devs worked around its behavior as one of the strange things in that universe. IIRC in several games you can drag knocked out guards around and your avatar gasps a limb while the victim rag dolls as you drag them. These simulations are actually very smooth and well implemented.

The quirky behavior in HL2 came from in essence a kinematic body forcing a rigid body against the environment and overdriving the physics simulation system (Havoc probbably)

@cybereality said: Joints should work. I found 6DOF Joint to be buggy and not work well (also listed as deprecated) so I used a simple Pin Joint and it seemed to work okay. You'd also have to limit the axis (lock) so it doesn't spin around wildly. But should be fine for simple HL2 style pickups.

I don't see 6dof as depreciated at all in the docs. There is complaint in engine about setting the params but that's because one of the parameter setting methods has been deprecated, not the joint.

6dof works, but the down side is the user interface in editor is not that nice, there is little documentation about the frame of referenced used by the joint (ie which node it is relative to) and you must have a good grasp of basic (rotationa/springl) physics and some idea of how simulations are performed.

A pin joint might seem nice until the carried object hits other physics elements, where the physics simulation will freak out.

@cybereality said: Joints should work. I found 6DOF Joint to be buggy and not work well (also listed as deprecated) so I used a simple Pin Joint and it seemed to work okay. You'd also have to limit the axis (lock) so it doesn't spin around wildly. But should be fine for simple HL2 style pickups.

Really? In my tests I had the exact opposite results. Pin joints work really poorly and 6DOF joints were superior in every way. Just as a note, I have already a working system that the object is nicely picked up using a 6DOF joint. However, I have trouble making it not get jammed into other collision objects. Quote from original post:

Not only this setup performs better than the formerly mentioned methods but also it reacts to external rigidbodies, forces, and collisions in a much more convincing way.

However, I'm having some trouble finalizing this setup. The biggest problem is when looking at a wall or the floor, it's easy to crush the object into a collision shape, making the physics system freak out. Essentially when looking at a wall up-close, the held object should be pushed closer to the player's face. I thought of moving the Joint position to the end of a raycast node casting from the player camera, but the problem with it is that, the picked up object is being moved around by its origin point and because of the size of the object it will result in half of the object still being crushed into a wall. Also if it gets too close to the player, it will crush into the player and will push the player in some direction.

I'm asking the community for help and for ideas on how to overcome these issues and finalize this into a setup that could be used in other projects as well. How do you think it's possible to control the position and physics handling of the picked up object so that it won't crush into the wall and the player?

@Leakbang said: It hit me out of nowhere that if the joint can be 'broken', it might solve the issue to some degree. I don't think that the Joints themselves have a breaking feature. But it might be possible to implement this via GDscript. Something like, if too much force is being applied to the held object, it simply drops. But that could introduce some new problems like the player having buttery fingers :D as everything falls from their hand with even slight collisions and also the fact that this would require a code to run every frame which defeats the point of this setup.

The problem is you don't really get force (delta velocity) information back.

Havoc implements a breaking system, but Bullet does not at least not exposed in godot.

You can test against distance divergence of the 'hand' and the object and sever the joint if a limit is exceeded.

Again, don't use a static body as a control. Bullet does not expect a static body to move in its simulation. If you want to move a rigid body via a joint, attach it to a kinematic body

Hmm... I don't know. Maybe I had the settings wrong since 6DOF seemed to not work right.

I went back and did some more research. The implementation in Half-Life 2 is just a series of duct tapes. It is not robust. I took a look at Soma again and the physics in that game really shine. Their in-house engine uses the Newton Dynamics physics engine. It's pretty good. This video showcases the object grabbing in Soma:

However in Godot, it seems that the Joint is holding the two objects together using an infinite amount of force. I believe limiting the force that the joint uses to hold the two nodes together would automatically solve this issue. But is it even possible to limit the value?

I loved SOMA. That thumbnail, tho, WTF!!!

I got it sort of working with the PinJoint.

The main trick is to lock angular axis while holding the object. Otherwise the physics bugs out. The other trick is to have the "hand" object (the thing that is attached to the object you are dragging) be a RigidBody but in mode Static. KinematicBodies don't work and normal StaticBodies don't work. You set visible to false and disable collisions for this hand object. The object you are grabbing is a normal RigidBody and the environment is a normal StaticBody. When you grab the object, you set the "hand" to be in the position of the center of the grabbed object, and then create a PinJoint attaching them. This works as long as you also lock all x/y/z angular axis on the grabbed object (and unlock when you let go). Otherwise things get crazy. But this is okay, as you probably don't want the object rotating as it's supposed to be in your hand. And to move, you can just move the hand object using normal methods, like adjusting the translation and the grabbed object follows. Seems to work alright.

I did try changing the staticbody 'hand' object to a rigidbody and to be honest no matter how much I tested it, I didn't see a difference. As for the axis lock, I'd say it's not helping at all. Even in your video, when the box is near the wall it starts to freak out. I played around more with the PinJoint but I still think 6DOF works better. Since there was no video of someone playing with the Soma physics, I reinstalled it and took a good look at how they did it. Their setup is surprisingly simple. They pretty much are also using a 6DOF Joint with a huge difference, it's the force limit. The joint setup that they have in Soma has a limit. In Godot that force is infinite, that's why the object is getting jammed in the wall and other horrible interactions are happening. In soma if the player tries to hold a heavy object like a chair, the chair is grabbed by the 'hand' joint, but because the weight of the chair is higher than the Joint's maximum force, the player can only limply push/drag it around. Bullet is pretty extensive... I'd reckon this must be implemented in it. This might already even exist in Godot. The question is how to do it. :s Perhaps tagging the engine contributors and bringing this post to their attention would also help.

I haven't tried any of this, but it seems like you want to carry a kinematic body, and then just destroy it and make an identical rigidbody when you want to let it loose with physics, or just hide it or something. Or else, just change the shape of the player kinematic body while carrying a mesh that represents it.

It already works, my video is almost there. The reason it was jumping on the wall is because I didn't put a constraint on the hand, (so it was clipping through the wall or behind it). In a real game, you would use ray casts or separate physics layers to stop the hand from getting into impossible positions, and this would work fine.

Bullet can definitely do it, it's fully featured, but I'm not sure how much is exposed in Godot. Theoretically the 6DOF Joint would be the answer, and might allow for greater range of movement (as with the Pin Joint you can't do rotations without it bugging out) but like I said, the 6DOF Joint is difficult to work with. But I'm sure you could do it in Godot, it's just that it's not well documented and no one has figured it out.

@fire7side that would work for simple stuff (like picking up a photo in Resident Evil) but in games like SOMA and HL2 the objects are part of the physics system. So you can be holding them and brush them against the wall and they will react realistically.