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?