How to properly use add_force in RigidBody (3D)

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By YoukaiCountry
:warning: Old Version Published before Godot 3 was released.

Hello, I’m new to Godot, and am trying to make the switch! RigidBody physics are giving me a little trouble at the moment, however:
I am trying to write a simple 3d game in which you move an object around in space via attached thrusters. To test that I have the basic physics working I created a RigidBody node, with an attached Spatial representing the thruster. Also attached is a CollisionShape (box)

I put the thruster on the bottom of the object, offset to the side a little bit. It should fire, rotating the object since it’s placed off to the side.

Here is the _integrate_forces code:

func _integrate_forces(state):
	var thruster = self.get_node("BottomThruster")
	var force_vector = thruster.get_global_transform().basis.y
	var pos = thruster.get_global_transform().origin

	state.add_force(force_vector, pos)

What happens is it thrusts and rotates just fine, until it is facing the scene origin, at which point it keeps going straight towards the origin. When it crosses over, it rotates back around to face the origin. It just keeps oscillating to face the origin at all times!

Is there something I am forgetting to do to update the body? Or am I not using the correct vector for force?
Thanks for the help!

:bust_in_silhouette: Reply From: Warlaan

You should have read the top questions first, I asked and later answered almost the same question myself just 12 hours ago.

The problem is that the wording on add_force (and apply_impulse) is a little ambiguous. It says that the offset is to be provided in world coordinates, but what it doesn’t say is that it still is to be given as an offset. So if you use the transform’s origin as the point where the force is applied it will NOT affect the center of the object but the position that is equally far from the object’s center than the object is from the world origin. That’s why the behaviour changes suddenly when you move past the origin.

Long story short: use
state.add_force(force_vector, Vector3(0,0,0))

I am trying to actually apply a force not at the center of the body, but at a certain object’s position. In my case then, I simply need to subtract the global position of the body being moved from the global thruster position, and now it works.

Thank you so much for the answer, it was exactly what I needed!

YoukaiCountry | 2016-10-03 09:49

Can you provide the code? Stuck here

Okan Ozdemir | 2019-12-18 17:27

Here is how I did:

extends RigidBody
class_name Rocket

export var thrust_vector = Vector3()

	
func _input(event):
	if (Input.is_key_pressed(KEY_UP)):
		var rocket_orientation: Vector3 = get_global_transform().basis[1]
		thrust_vector = Vector3(0.0, 13.0, 0.0)
		var rotation_axis: Vector3 = thrust_vector.cross(rocket_orientation).normalized()
		var angle = thrust_vector.angle_to(rocket_orientation)
		thrust_vector = thrust_vector.rotated(rotation_axis, angle)
	else:
		thrust_vector = Vector3()


func _integrate_forces(state):
	var boosters_position = get_node("Boosters").get_global_transform().origin
	var rocket_position = get_global_transform().origin
	add_force(thrust_vector, rocket_position - boosters_position)

Monstercrunch | 2020-12-01 19:25

@YoukaiCountry any chance we could play a demo of your game? B-)

cholasimmons | 2023-03-26 06:36