How to create a 3D joint which allows only translation into one direction?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Pixelcook

Hi all,

I am new to Godot and as a learning project for Godot I want to build a small 3D game in which you have to land a spaceship.
Yesterday I spend the whole evening trying to figure out how to configure joints in Godot. But either I completely miss some important things or joints are somewhat broken in Godot 3.
I want to attach a landing gear to the spaceship which can only move in the local y direction of the space ship. This landing gear should work as a shock absorber (spring+damper).
First I was happy to find the “SliderJoint”, which seems to be exactly the thing I need. But somehow it moved (and also turned!) in all directions and changing the softness, restitution and damping values did not really change anything.
So I switched to the generic “Generic6DOFJoint” for which the documentation states that you should be able to “lock” certain axes. But I could only find the option to “enable” an axis. If I do not enable it, the landing gear freely falls down in this direction. If I enable it, it is again extremely “soft” whatever softness, restitution and damping values I set. It has not even to touch the ground. It is enough to move the spaceship around in air and the landing gear is freely wobbling around like a rubber spring.
I coded some fake physics applying impulses to the spaceship to make the landing gear acting as spring and damper when touching the ground without being completely crushed by the ship, but the gear is still turning to the side at landing and it looks and acts like it is made out of rubber when the spaceship stands on it.

I could not found an explanation of the joints in the Internet, only people having similar problems:
https://forum.godotengine.org/26525/how-can-you-constraint-two-adjacent-rigid-body-they-were-part?show=26556#c26556
https://forum.godotengine.org/19534/how-to-make-a-rigid-joint-between-two-rigidbodies?show=19534#q19534
https://forum.godotengine.org/30990/generic6dofjoint-too-soft?show=30990#q30990

I really hope joints are not broken in Godot (3.04) and somebody knows how to use them. Otherwise I have to code the whole joint interaction in GDScript which is not a nice way to achieve something that simple.

Thanks for reading my question! :slight_smile:

:bust_in_silhouette: Reply From: Pixelcook

I have fixed my case, but I cannot give a simple advice how to do it. Also I do not know if some of the things I have done are not necessary to make it work.

So here is what I have done:

Joints
After switching them a lot of times I used Generic6DOFJoints in the end, but SliderJoints may work as well.
I positioned the joints exactly at the connection point between the different parts to avoid any additional momentum at the joint.

Parameters for the Joints
I defined an upper and lower distance for the linear limit to let the joint freely move inside of this. The softness for the linear limit and the linear motion I set to one and in all other categories to 0.5. Restitution I set to 16 in all categories as well as damping to 0.01 in all categories.

Code
This is the longest part were I tried out a lot of different things. I do not know how good my code is since I am still a little bit confused by the different _integrate_forces etc. functions.
Since the joint physics is not usable, I coded the spring+damper physics as GDScripts. If you know how to do this, you do not need to read the rest of this post. For people who want to do similar things I explain everything I have down in the following text:

Landing gear

_ready()
The landing gears share a common script. In the _ready() function they save the length of the offset vector between their origin and the origin of the ship into a global variable. This length is used as reference length for the virtual spring.

_physics_process(delta)
In the _physics_process(delta) function the linear velocity of the ship and the current offset vector between the ship and the landing gear is read. Afterwards the angular velocity of the ship is read and added to the relative velocity in relation to the landing gear position. This is done by multiplying the different components of the offset vector with the different components of the angular rotation vector and an unit vector into the resulting velocity direction for each combination.
In the end the calculated ship velocity at the attachment point of the landing gear is subtracted from the linear velocity of the landing gear and the dot product of this vector with the vertical direction of the ship is calculated. The result is the velocity difference in the movement direction of the landing gear. This is saved into a global variable.

_integrate_forces(state)
In _integrate_forces(state) the length of the current offset vector between the origins of the ship and the landing gear is calculated and subtracted from the reference length to get the length difference for the spring. Then the force of the spring is calculating by multiplying this length difference with a factor and the force of the damping is calculated by multiplying the global velocity difference variable from the _physics_process(delta) function with a factor.
I also added a constant dry friction force depending on the direction of relative movement, to stop oscillation movements faster without crazy physics which I get by adding too much damping.
The force is saved in a global variable which is later used by the ship.
In the end the landing gear is checked for collisions (with the ground) and if it collides the linear velocity is manually set to the velocity of the colliding object.
If it does not collide it is checked if it is very near or outside the linear limits of the joint and in this case its velocity is set to the velocity of the ship and the weight pointing into y direction is added as a force, to avoid it falling down and starting to oscillate in some situations.
Otherwise the negative force from spring, damping and friction are applied to it.

Ship

_process(delta)
All user controls are applied in _process(delta) as impulses.

_integrate_forces(state)
Here the global force variables of all landing gears are read and added as forces in the upwards direction of the ship (in which the landing gear always should be pointing if the joints would not be so floppy)