Browse Source

Merge pull request #55736 from nekomatata/physics-apply-forces

Improve RigidDynamicBody force and torque API
Camille Mohr-Daurat 3 years ago
parent
commit
f1ca14cc8d

+ 70 - 9
doc/classes/PhysicsDirectBodyState2D.xml

@@ -11,26 +11,36 @@
 		<link title="Ray-casting">$DOCS_URL/tutorials/physics/ray-casting.html</link>
 	</tutorials>
 	<methods>
-		<method name="add_central_force">
+		<method name="add_constant_central_force">
 			<return type="void" />
-			<argument index="0" name="force" type="Vector2" />
+			<argument index="0" name="force" type="Vector2" default="Vector2(0, 0)" />
 			<description>
-				Adds a constant directional force without affecting rotation.
+				Adds a constant directional force without affecting rotation that keeps being applied over time until cleared with [code]constant_force = Vector2(0, 0)[/code].
+				This is equivalent to using [method add_constant_force] at the body's center of mass.
 			</description>
 		</method>
-		<method name="add_force">
+		<method name="add_constant_force">
 			<return type="void" />
 			<argument index="0" name="force" type="Vector2" />
 			<argument index="1" name="position" type="Vector2" default="Vector2(0, 0)" />
 			<description>
-				Adds a positioned force to the body. Both the force and the offset from the body origin are in global coordinates.
+				Adds a constant positioned force to the body that keeps being applied over time until cleared with [code]constant_force = Vector2(0, 0)[/code].
+				[code]position[/code] is the offset from the body origin in global coordinates.
 			</description>
 		</method>
-		<method name="add_torque">
+		<method name="add_constant_torque">
 			<return type="void" />
 			<argument index="0" name="torque" type="float" />
 			<description>
-				Adds a constant rotational force.
+				Adds a constant rotational force without affecting position that keeps being applied over time until cleared with [code]constant_torque = 0[/code].
+			</description>
+		</method>
+		<method name="apply_central_force">
+			<return type="void" />
+			<argument index="0" name="force" type="Vector2" default="Vector2(0, 0)" />
+			<description>
+				Applies a directional force without affecting rotation. A force is time dependent and meant to be applied every physics update.
+				This is equivalent to using [method apply_force] at the body's center of mass.
 			</description>
 		</method>
 		<method name="apply_central_impulse">
@@ -38,6 +48,17 @@
 			<argument index="0" name="impulse" type="Vector2" />
 			<description>
 				Applies a directional impulse without affecting rotation.
+				An impulse is time-independent! Applying an impulse every frame would result in a framerate-dependent force. For this reason, it should only be used when simulating one-time impacts (use the "_force" functions otherwise).
+				This is equivalent to using [method apply_impulse] at the body's center of mass.
+			</description>
+		</method>
+		<method name="apply_force">
+			<return type="void" />
+			<argument index="0" name="force" type="Vector2" />
+			<argument index="1" name="position" type="Vector2" default="Vector2(0, 0)" />
+			<description>
+				Applies a positioned force to the body. A force is time dependent and meant to be applied every physics update.
+				[code]position[/code] is the offset from the body origin in global coordinates.
 			</description>
 		</method>
 		<method name="apply_impulse">
@@ -45,14 +66,38 @@
 			<argument index="0" name="impulse" type="Vector2" />
 			<argument index="1" name="position" type="Vector2" default="Vector2(0, 0)" />
 			<description>
-				Applies a positioned impulse to the body. An impulse is time-independent! Applying an impulse every frame would result in a framerate-dependent force. For this reason, it should only be used when simulating one-time impacts (use the "_force" functions otherwise). The offset uses the rotation of the global coordinate system, but is centered at the object's origin.
+				Applies a positioned impulse to the body.
+				An impulse is time-independent! Applying an impulse every frame would result in a framerate-dependent force. For this reason, it should only be used when simulating one-time impacts (use the "_force" functions otherwise).
+				[code]position[/code] is the offset from the body origin in global coordinates.
+			</description>
+		</method>
+		<method name="apply_torque">
+			<return type="void" />
+			<argument index="0" name="torque" type="float" />
+			<description>
+				Applies a rotational force without affecting position. A force is time dependent and meant to be applied every physics update.
 			</description>
 		</method>
 		<method name="apply_torque_impulse">
 			<return type="void" />
 			<argument index="0" name="impulse" type="float" />
 			<description>
-				Applies a rotational impulse to the body.
+				Applies a rotational impulse to the body without affecting the position.
+				An impulse is time-independent! Applying an impulse every frame would result in a framerate-dependent force. For this reason, it should only be used when simulating one-time impacts (use the "_force" functions otherwise).
+			</description>
+		</method>
+		<method name="get_constant_force" qualifiers="const">
+			<return type="Vector2" />
+			<description>
+				Returns the body's total constant positional forces applied during each physics update.
+				See [method add_constant_force] and [method add_constant_central_force].
+			</description>
+		</method>
+		<method name="get_constant_torque" qualifiers="const">
+			<return type="float" />
+			<description>
+				Returns the body's total constant rotational forces applied during each physics update.
+				See [method add_constant_torque].
 			</description>
 		</method>
 		<method name="get_contact_collider" qualifiers="const">
@@ -144,6 +189,22 @@
 				Calls the built-in force integration code.
 			</description>
 		</method>
+		<method name="set_constant_force">
+			<return type="void" />
+			<argument index="0" name="force" type="Vector2" />
+			<description>
+				Sets the body's total constant positional forces applied during each physics update.
+				See [method add_constant_force] and [method add_constant_central_force].
+			</description>
+		</method>
+		<method name="set_constant_torque">
+			<return type="void" />
+			<argument index="0" name="torque" type="float" />
+			<description>
+				Sets the body's total constant rotational forces applied during each physics update.
+				See [method add_constant_torque].
+			</description>
+		</method>
 	</methods>
 	<members>
 		<member name="angular_velocity" type="float" setter="set_angular_velocity" getter="get_angular_velocity">

+ 70 - 11
doc/classes/PhysicsDirectBodyState3D.xml

@@ -11,35 +11,54 @@
 		<link title="Ray-casting">$DOCS_URL/tutorials/physics/ray-casting.html</link>
 	</tutorials>
 	<methods>
-		<method name="add_central_force">
+		<method name="add_constant_central_force">
 			<return type="void" />
 			<argument index="0" name="force" type="Vector3" default="Vector3(0, 0, 0)" />
 			<description>
-				Adds a constant directional force without affecting rotation.
-				This is equivalent to [code]add_force(force, Vector3(0,0,0))[/code].
+				Adds a constant directional force without affecting rotation that keeps being applied over time until cleared with [code]constant_force = Vector3(0, 0, 0)[/code].
+				This is equivalent to using [method add_constant_force] at the body's center of mass.
 			</description>
 		</method>
-		<method name="add_force">
+		<method name="add_constant_force">
 			<return type="void" />
 			<argument index="0" name="force" type="Vector3" />
 			<argument index="1" name="position" type="Vector3" default="Vector3(0, 0, 0)" />
 			<description>
-				Adds a positioned force to the body. Both the force and the offset from the body origin are in global coordinates.
+				Adds a constant positioned force to the body that keeps being applied over time until cleared with [code]constant_force = Vector3(0, 0, 0)[/code].
+				[code]position[/code] is the offset from the body origin in global coordinates.
 			</description>
 		</method>
-		<method name="add_torque">
+		<method name="add_constant_torque">
 			<return type="void" />
 			<argument index="0" name="torque" type="Vector3" />
 			<description>
-				Adds a constant rotational force without affecting position.
+				Adds a constant rotational force without affecting position that keeps being applied over time until cleared with [code]constant_torque = Vector3(0, 0, 0)[/code].
+			</description>
+		</method>
+		<method name="apply_central_force">
+			<return type="void" />
+			<argument index="0" name="force" type="Vector3" default="Vector3(0, 0, 0)" />
+			<description>
+				Applies a directional force without affecting rotation. A force is time dependent and meant to be applied every physics update.
+				This is equivalent to using [method apply_force] at the body's center of mass.
 			</description>
 		</method>
 		<method name="apply_central_impulse">
 			<return type="void" />
 			<argument index="0" name="impulse" type="Vector3" default="Vector3(0, 0, 0)" />
 			<description>
-				Applies a single directional impulse without affecting rotation.
-				This is equivalent to [code]apply_impulse(Vector3(0, 0, 0), impulse)[/code].
+				Applies a directional impulse without affecting rotation.
+				An impulse is time-independent! Applying an impulse every frame would result in a framerate-dependent force. For this reason, it should only be used when simulating one-time impacts (use the "_force" functions otherwise).
+				This is equivalent to using [method apply_impulse] at the body's center of mass.
+			</description>
+		</method>
+		<method name="apply_force">
+			<return type="void" />
+			<argument index="0" name="force" type="Vector3" />
+			<argument index="1" name="position" type="Vector3" default="Vector3(0, 0, 0)" />
+			<description>
+				Applies a positioned force to the body. A force is time dependent and meant to be applied every physics update.
+				[code]position[/code] is the offset from the body origin in global coordinates.
 			</description>
 		</method>
 		<method name="apply_impulse">
@@ -47,14 +66,38 @@
 			<argument index="0" name="impulse" type="Vector3" />
 			<argument index="1" name="position" type="Vector3" default="Vector3(0, 0, 0)" />
 			<description>
-				Applies a positioned impulse to the body. An impulse is time-independent! Applying an impulse every frame would result in a framerate-dependent force. For this reason it should only be used when simulating one-time impacts. The position uses the rotation of the global coordinate system, but is centered at the object's origin.
+				Applies a positioned impulse to the body.
+				An impulse is time-independent! Applying an impulse every frame would result in a framerate-dependent force. For this reason, it should only be used when simulating one-time impacts (use the "_force" functions otherwise).
+				[code]position[/code] is the offset from the body origin in global coordinates.
+			</description>
+		</method>
+		<method name="apply_torque">
+			<return type="void" />
+			<argument index="0" name="torque" type="Vector3" />
+			<description>
+				Applies a rotational force without affecting position. A force is time dependent and meant to be applied every physics update.
 			</description>
 		</method>
 		<method name="apply_torque_impulse">
 			<return type="void" />
 			<argument index="0" name="impulse" type="Vector3" />
 			<description>
-				Apply a torque impulse (which will be affected by the body mass and shape). This will rotate the body around the vector [code]j[/code] passed as parameter.
+				Applies a rotational impulse to the body without affecting the position.
+				An impulse is time-independent! Applying an impulse every frame would result in a framerate-dependent force. For this reason, it should only be used when simulating one-time impacts (use the "_force" functions otherwise).
+			</description>
+		</method>
+		<method name="get_constant_force" qualifiers="const">
+			<return type="Vector3" />
+			<description>
+				Returns the body's total constant positional forces applied during each physics update.
+				See [method add_constant_force] and [method add_constant_central_force].
+			</description>
+		</method>
+		<method name="get_constant_torque" qualifiers="const">
+			<return type="Vector3" />
+			<description>
+				Returns the body's total constant rotational forces applied during each physics update.
+				See [method add_constant_torque].
 			</description>
 		</method>
 		<method name="get_contact_collider" qualifiers="const">
@@ -153,6 +196,22 @@
 				Calls the built-in force integration code.
 			</description>
 		</method>
+		<method name="set_constant_force">
+			<return type="void" />
+			<argument index="0" name="force" type="Vector3" />
+			<description>
+				Sets the body's total constant positional forces applied during each physics update.
+				See [method add_constant_force] and [method add_constant_central_force].
+			</description>
+		</method>
+		<method name="set_constant_torque">
+			<return type="void" />
+			<argument index="0" name="torque" type="Vector3" />
+			<description>
+				Sets the body's total constant rotational forces applied during each physics update.
+				See [method add_constant_torque].
+			</description>
+		</method>
 	</methods>
 	<members>
 		<member name="angular_velocity" type="Vector3" setter="set_angular_velocity" getter="get_angular_velocity">

+ 82 - 10
doc/classes/PhysicsServer2D.xml

@@ -208,28 +208,39 @@
 				Sets the transform matrix for an area.
 			</description>
 		</method>
-		<method name="body_add_central_force">
+		<method name="body_add_collision_exception">
 			<return type="void" />
 			<argument index="0" name="body" type="RID" />
-			<argument index="1" name="force" type="Vector2" />
+			<argument index="1" name="excepted_body" type="RID" />
 			<description>
+				Adds a body to the list of bodies exempt from collisions.
 			</description>
 		</method>
-		<method name="body_add_collision_exception">
+		<method name="body_add_constant_central_force">
 			<return type="void" />
 			<argument index="0" name="body" type="RID" />
-			<argument index="1" name="excepted_body" type="RID" />
+			<argument index="1" name="force" type="Vector2" />
 			<description>
-				Adds a body to the list of bodies exempt from collisions.
+				Adds a constant directional force without affecting rotation that keeps being applied over time until cleared with [code]body_set_constant_force(body, Vector2(0, 0))[/code].
+				This is equivalent to using [method body_add_constant_force] at the body's center of mass.
 			</description>
 		</method>
-		<method name="body_add_force">
+		<method name="body_add_constant_force">
 			<return type="void" />
 			<argument index="0" name="body" type="RID" />
 			<argument index="1" name="force" type="Vector2" />
 			<argument index="2" name="position" type="Vector2" default="Vector2(0, 0)" />
 			<description>
-				Adds a positioned force to the applied force and torque. As with [method body_apply_impulse], both the force and the offset from the body origin are in global coordinates. A force differs from an impulse in that, while the two are forces, the impulse clears itself after being applied.
+				Adds a constant positioned force to the body that keeps being applied over time until cleared with [code]body_set_constant_force(body, Vector2(0, 0))[/code].
+				[code]position[/code] is the offset from the body origin in global coordinates.
+			</description>
+		</method>
+		<method name="body_add_constant_torque">
+			<return type="void" />
+			<argument index="0" name="body" type="RID" />
+			<argument index="1" name="torque" type="float" />
+			<description>
+				Adds a constant rotational force without affecting position that keeps being applied over time until cleared with [code]body_set_constant_torque(body, 0)[/code].
 			</description>
 		</method>
 		<method name="body_add_shape">
@@ -242,11 +253,13 @@
 				Adds a shape to the body, along with a transform matrix. Shapes are usually referenced by their index, so you should track which shape has a given index.
 			</description>
 		</method>
-		<method name="body_add_torque">
+		<method name="body_apply_central_force">
 			<return type="void" />
 			<argument index="0" name="body" type="RID" />
-			<argument index="1" name="torque" type="float" />
+			<argument index="1" name="force" type="Vector2" />
 			<description>
+				Applies a directional force without affecting rotation. A force is time dependent and meant to be applied every physics update.
+				This is equivalent to using [method body_apply_force] at the body's center of mass.
 			</description>
 		</method>
 		<method name="body_apply_central_impulse">
@@ -254,6 +267,19 @@
 			<argument index="0" name="body" type="RID" />
 			<argument index="1" name="impulse" type="Vector2" />
 			<description>
+				Applies a directional impulse without affecting rotation.
+				An impulse is time-independent! Applying an impulse every frame would result in a framerate-dependent force. For this reason, it should only be used when simulating one-time impacts (use the "_force" functions otherwise).
+				This is equivalent to using [method body_apply_impulse] at the body's center of mass.
+			</description>
+		</method>
+		<method name="body_apply_force">
+			<return type="void" />
+			<argument index="0" name="body" type="RID" />
+			<argument index="1" name="force" type="Vector2" />
+			<argument index="2" name="position" type="Vector2" default="Vector2(0, 0)" />
+			<description>
+				Applies a positioned force to the body. A force is time dependent and meant to be applied every physics update.
+				[code]position[/code] is the offset from the body origin in global coordinates.
 			</description>
 		</method>
 		<method name="body_apply_impulse">
@@ -262,7 +288,17 @@
 			<argument index="1" name="impulse" type="Vector2" />
 			<argument index="2" name="position" type="Vector2" default="Vector2(0, 0)" />
 			<description>
-				Adds a positioned impulse to the applied force and torque. Both the force and the offset from the body origin are in global coordinates.
+				Applies a positioned impulse to the body.
+				An impulse is time-independent! Applying an impulse every frame would result in a framerate-dependent force. For this reason, it should only be used when simulating one-time impacts (use the "_force" functions otherwise).
+				[code]position[/code] is the offset from the body origin in global coordinates.
+			</description>
+		</method>
+		<method name="body_apply_torque">
+			<return type="void" />
+			<argument index="0" name="body" type="RID" />
+			<argument index="1" name="torque" type="float" />
+			<description>
+				Applies a rotational force without affecting position. A force is time dependent and meant to be applied every physics update.
 			</description>
 		</method>
 		<method name="body_apply_torque_impulse">
@@ -270,6 +306,8 @@
 			<argument index="0" name="body" type="RID" />
 			<argument index="1" name="impulse" type="float" />
 			<description>
+				Applies a rotational impulse to the body without affecting the position.
+				An impulse is time-independent! Applying an impulse every frame would result in a framerate-dependent force. For this reason, it should only be used when simulating one-time impacts (use the "_force" functions otherwise).
 			</description>
 		</method>
 		<method name="body_attach_canvas_instance_id">
@@ -320,6 +358,22 @@
 				Returns the physics layer or layers a body can collide with.
 			</description>
 		</method>
+		<method name="body_get_constant_force" qualifiers="const">
+			<return type="Vector2" />
+			<argument index="0" name="body" type="RID" />
+			<description>
+				Returns the body's total constant positional forces applied during each physics update.
+				See [method body_add_constant_force] and [method body_add_constant_central_force].
+			</description>
+		</method>
+		<method name="body_get_constant_torque" qualifiers="const">
+			<return type="float" />
+			<argument index="0" name="body" type="RID" />
+			<description>
+				Returns the body's total constant rotational forces applied during each physics update.
+				See [method body_add_constant_torque].
+			</description>
+		</method>
 		<method name="body_get_continuous_collision_detection_mode" qualifiers="const">
 			<return type="int" enum="PhysicsServer2D.CCDMode" />
 			<argument index="0" name="body" type="RID" />
@@ -455,6 +509,24 @@
 				Sets the physics layer or layers a body can collide with.
 			</description>
 		</method>
+		<method name="body_set_constant_force">
+			<return type="void" />
+			<argument index="0" name="body" type="RID" />
+			<argument index="1" name="force" type="Vector2" />
+			<description>
+				Sets the body's total constant positional forces applied during each physics update.
+				See [method body_add_constant_force] and [method body_add_constant_central_force].
+			</description>
+		</method>
+		<method name="body_set_constant_torque">
+			<return type="void" />
+			<argument index="0" name="body" type="RID" />
+			<argument index="1" name="torque" type="float" />
+			<description>
+				Sets the body's total constant rotational forces applied during each physics update.
+				See [method body_add_constant_torque].
+			</description>
+		</method>
 		<method name="body_set_continuous_collision_detection_mode">
 			<return type="void" />
 			<argument index="0" name="body" type="RID" />

+ 82 - 10
doc/classes/PhysicsServer3D.xml

@@ -202,27 +202,39 @@
 				Sets the transform matrix for an area.
 			</description>
 		</method>
-		<method name="body_add_central_force">
+		<method name="body_add_collision_exception">
 			<return type="void" />
 			<argument index="0" name="body" type="RID" />
-			<argument index="1" name="force" type="Vector3" />
+			<argument index="1" name="excepted_body" type="RID" />
 			<description>
+				Adds a body to the list of bodies exempt from collisions.
 			</description>
 		</method>
-		<method name="body_add_collision_exception">
+		<method name="body_add_constant_central_force">
 			<return type="void" />
 			<argument index="0" name="body" type="RID" />
-			<argument index="1" name="excepted_body" type="RID" />
+			<argument index="1" name="force" type="Vector3" />
 			<description>
-				Adds a body to the list of bodies exempt from collisions.
+				Adds a constant directional force without affecting rotation that keeps being applied over time until cleared with [code]body_set_constant_force(body, Vector3(0, 0, 0))[/code].
+				This is equivalent to using [method body_add_constant_force] at the body's center of mass.
 			</description>
 		</method>
-		<method name="body_add_force">
+		<method name="body_add_constant_force">
 			<return type="void" />
 			<argument index="0" name="body" type="RID" />
 			<argument index="1" name="force" type="Vector3" />
 			<argument index="2" name="position" type="Vector3" default="Vector3(0, 0, 0)" />
 			<description>
+				Adds a constant positioned force to the body that keeps being applied over time until cleared with [code]body_set_constant_force(body, Vector3(0, 0, 0))[/code].
+				[code]position[/code] is the offset from the body origin in global coordinates.
+			</description>
+		</method>
+		<method name="body_add_constant_torque">
+			<return type="void" />
+			<argument index="0" name="body" type="RID" />
+			<argument index="1" name="torque" type="Vector3" />
+			<description>
+				Adds a constant rotational force without affecting position that keeps being applied over time until cleared with [code]body_set_constant_torque(body, Vector3(0, 0, 0))[/code].
 			</description>
 		</method>
 		<method name="body_add_shape">
@@ -235,11 +247,13 @@
 				Adds a shape to the body, along with a transform matrix. Shapes are usually referenced by their index, so you should track which shape has a given index.
 			</description>
 		</method>
-		<method name="body_add_torque">
+		<method name="body_apply_central_force">
 			<return type="void" />
 			<argument index="0" name="body" type="RID" />
-			<argument index="1" name="torque" type="Vector3" />
+			<argument index="1" name="force" type="Vector3" />
 			<description>
+				Applies a directional force without affecting rotation. A force is time dependent and meant to be applied every physics update.
+				This is equivalent to using [method body_apply_force] at the body's center of mass.
 			</description>
 		</method>
 		<method name="body_apply_central_impulse">
@@ -247,6 +261,19 @@
 			<argument index="0" name="body" type="RID" />
 			<argument index="1" name="impulse" type="Vector3" />
 			<description>
+				Applies a directional impulse without affecting rotation.
+				An impulse is time-independent! Applying an impulse every frame would result in a framerate-dependent force. For this reason, it should only be used when simulating one-time impacts (use the "_force" functions otherwise).
+				This is equivalent to using [method body_apply_impulse] at the body's center of mass.
+			</description>
+		</method>
+		<method name="body_apply_force">
+			<return type="void" />
+			<argument index="0" name="body" type="RID" />
+			<argument index="1" name="force" type="Vector3" />
+			<argument index="2" name="position" type="Vector3" default="Vector3(0, 0, 0)" />
+			<description>
+				Applies a positioned force to the body. A force is time dependent and meant to be applied every physics update.
+				[code]position[/code] is the offset from the body origin in global coordinates.
 			</description>
 		</method>
 		<method name="body_apply_impulse">
@@ -255,7 +282,17 @@
 			<argument index="1" name="impulse" type="Vector3" />
 			<argument index="2" name="position" type="Vector3" default="Vector3(0, 0, 0)" />
 			<description>
-				Gives the body a push at a [code]position[/code] in the direction of the [code]impulse[/code].
+				Applies a positioned impulse to the body.
+				An impulse is time-independent! Applying an impulse every frame would result in a framerate-dependent force. For this reason, it should only be used when simulating one-time impacts (use the "_force" functions otherwise).
+				[code]position[/code] is the offset from the body origin in global coordinates.
+			</description>
+		</method>
+		<method name="body_apply_torque">
+			<return type="void" />
+			<argument index="0" name="body" type="RID" />
+			<argument index="1" name="torque" type="Vector3" />
+			<description>
+				Applies a rotational force without affecting position. A force is time dependent and meant to be applied every physics update.
 			</description>
 		</method>
 		<method name="body_apply_torque_impulse">
@@ -263,7 +300,8 @@
 			<argument index="0" name="body" type="RID" />
 			<argument index="1" name="impulse" type="Vector3" />
 			<description>
-				Gives the body a push to rotate it.
+				Applies a rotational impulse to the body without affecting the position.
+				An impulse is time-independent! Applying an impulse every frame would result in a framerate-dependent force. For this reason, it should only be used when simulating one-time impacts (use the "_force" functions otherwise).
 			</description>
 		</method>
 		<method name="body_attach_object_instance_id">
@@ -301,6 +339,22 @@
 -
 			</description>
 		</method>
+		<method name="body_get_constant_force" qualifiers="const">
+			<return type="Vector3" />
+			<argument index="0" name="body" type="RID" />
+			<description>
+				Returns the body's total constant positional forces applied during each physics update.
+				See [method body_add_constant_force] and [method body_add_constant_central_force].
+			</description>
+		</method>
+		<method name="body_get_constant_torque" qualifiers="const">
+			<return type="Vector3" />
+			<argument index="0" name="body" type="RID" />
+			<description>
+				Returns the body's total constant rotational forces applied during each physics update.
+				See [method body_add_constant_torque].
+			</description>
+		</method>
 		<method name="body_get_direct_state">
 			<return type="PhysicsDirectBodyState3D" />
 			<argument index="0" name="body" type="RID" />
@@ -452,6 +506,24 @@
 				Sets the physics layer or layers a body can collide with.
 			</description>
 		</method>
+		<method name="body_set_constant_force">
+			<return type="void" />
+			<argument index="0" name="body" type="RID" />
+			<argument index="1" name="force" type="Vector3" />
+			<description>
+				Sets the body's total constant positional forces applied during each physics update.
+				See [method body_add_constant_force] and [method body_add_constant_central_force].
+			</description>
+		</method>
+		<method name="body_set_constant_torque">
+			<return type="void" />
+			<argument index="0" name="body" type="RID" />
+			<argument index="1" name="torque" type="Vector3" />
+			<description>
+				Sets the body's total constant rotational forces applied during each physics update.
+				See [method body_add_constant_torque].
+			</description>
+		</method>
 		<method name="body_set_enable_continuous_collision_detection">
 			<return type="void" />
 			<argument index="0" name="body" type="RID" />

+ 48 - 15
doc/classes/RigidDynamicBody2D.xml

@@ -22,26 +22,36 @@
 				Allows you to read and safely modify the simulation state for the object. Use this instead of [method Node._physics_process] if you need to directly change the body's [code]position[/code] or other physics properties. By default, it works in addition to the usual physics behavior, but [member custom_integrator] allows you to disable the default behavior and write custom force integration for a body.
 			</description>
 		</method>
-		<method name="add_central_force">
+		<method name="add_constant_central_force">
 			<return type="void" />
 			<argument index="0" name="force" type="Vector2" />
 			<description>
-				Adds a constant directional force without affecting rotation.
+				Adds a constant directional force without affecting rotation that keeps being applied over time until cleared with [code]constant_force = Vector2(0, 0)[/code].
+				This is equivalent to using [method add_constant_force] at the body's center of mass.
 			</description>
 		</method>
-		<method name="add_force">
+		<method name="add_constant_force">
 			<return type="void" />
 			<argument index="0" name="force" type="Vector2" />
 			<argument index="1" name="position" type="Vector2" default="Vector2(0, 0)" />
 			<description>
-				Adds a positioned force to the body. Both the force and the offset from the body origin are in global coordinates.
+				Adds a constant positioned force to the body that keeps being applied over time until cleared with [code]constant_force = Vector2(0, 0)[/code].
+				[code]position[/code] is the offset from the body origin in global coordinates.
 			</description>
 		</method>
-		<method name="add_torque">
+		<method name="add_constant_torque">
 			<return type="void" />
 			<argument index="0" name="torque" type="float" />
 			<description>
-				Adds a constant rotational force.
+				Adds a constant rotational force without affecting position that keeps being applied over time until cleared with [code]constant_torque = 0[/code].
+			</description>
+		</method>
+		<method name="apply_central_force">
+			<return type="void" />
+			<argument index="0" name="force" type="Vector2" />
+			<description>
+				Applies a directional force without affecting rotation. A force is time dependent and meant to be applied every physics update.
+				This is equivalent to using [method apply_force] at the body's center of mass.
 			</description>
 		</method>
 		<method name="apply_central_impulse">
@@ -49,6 +59,17 @@
 			<argument index="0" name="impulse" type="Vector2" default="Vector2(0, 0)" />
 			<description>
 				Applies a directional impulse without affecting rotation.
+				An impulse is time-independent! Applying an impulse every frame would result in a framerate-dependent force. For this reason, it should only be used when simulating one-time impacts (use the "_force" functions otherwise).
+				This is equivalent to using [method apply_impulse] at the body's center of mass.
+			</description>
+		</method>
+		<method name="apply_force">
+			<return type="void" />
+			<argument index="0" name="force" type="Vector2" />
+			<argument index="1" name="position" type="Vector2" default="Vector2(0, 0)" />
+			<description>
+				Applies a positioned force to the body. A force is time dependent and meant to be applied every physics update.
+				[code]position[/code] is the offset from the body origin in global coordinates.
 			</description>
 		</method>
 		<method name="apply_impulse">
@@ -56,14 +77,24 @@
 			<argument index="0" name="impulse" type="Vector2" />
 			<argument index="1" name="position" type="Vector2" default="Vector2(0, 0)" />
 			<description>
-				Applies a positioned impulse to the body. An impulse is time-independent! Applying an impulse every frame would result in a framerate-dependent force. For this reason it should only be used when simulating one-time impacts (use the "_force" functions otherwise). The position uses the rotation of the global coordinate system, but is centered at the object's origin.
+				Applies a positioned impulse to the body.
+				An impulse is time-independent! Applying an impulse every frame would result in a framerate-dependent force. For this reason, it should only be used when simulating one-time impacts (use the "_force" functions otherwise).
+				[code]position[/code] is the offset from the body origin in global coordinates.
+			</description>
+		</method>
+		<method name="apply_torque">
+			<return type="void" />
+			<argument index="0" name="torque" type="float" />
+			<description>
+				Applies a rotational force without affecting position. A force is time dependent and meant to be applied every physics update.
 			</description>
 		</method>
 		<method name="apply_torque_impulse">
 			<return type="void" />
 			<argument index="0" name="torque" type="float" />
 			<description>
-				Applies a rotational impulse to the body.
+				Applies a rotational impulse to the body without affecting the position.
+				An impulse is time-independent! Applying an impulse every frame would result in a framerate-dependent force. For this reason, it should only be used when simulating one-time impacts (use the "_force" functions otherwise).
 			</description>
 		</method>
 		<method name="get_colliding_bodies" qualifiers="const">
@@ -92,12 +123,6 @@
 		<member name="angular_velocity" type="float" setter="set_angular_velocity" getter="get_angular_velocity" default="0.0">
 			The body's rotational velocity.
 		</member>
-		<member name="applied_force" type="Vector2" setter="set_applied_force" getter="get_applied_force" default="Vector2(0, 0)">
-			The body's total applied force.
-		</member>
-		<member name="applied_torque" type="float" setter="set_applied_torque" getter="get_applied_torque" default="0.0">
-			The body's total applied torque.
-		</member>
 		<member name="can_sleep" type="bool" setter="set_can_sleep" getter="is_able_to_sleep" default="true">
 			If [code]true[/code], the body can enter sleep mode when there is no movement. See [member sleeping].
 		</member>
@@ -108,6 +133,14 @@
 		<member name="center_of_mass_mode" type="int" setter="set_center_of_mass_mode" getter="get_center_of_mass_mode" enum="RigidDynamicBody2D.CenterOfMassMode" default="0">
 			Defines the way the body's center of mass is set. See [enum CenterOfMassMode] for possible values.
 		</member>
+		<member name="constant_force" type="Vector2" setter="set_constant_force" getter="get_constant_force" default="Vector2(0, 0)">
+			The body's total constant positional forces applied during each physics update.
+			See [method add_constant_force] and [method add_constant_central_force].
+		</member>
+		<member name="constant_torque" type="float" setter="set_constant_torque" getter="get_constant_torque" default="0.0">
+			The body's total constant rotational forces applied during each physics update.
+			See [method add_constant_torque].
+		</member>
 		<member name="contact_monitor" type="bool" setter="set_contact_monitor" getter="is_contact_monitor_enabled" default="false">
 			If [code]true[/code], the body will emit signals when it collides with another RigidDynamicBody2D. See also [member contacts_reported].
 		</member>
@@ -159,7 +192,7 @@
 			If a material is assigned to this property, it will be used instead of any other physics material, such as an inherited one.
 		</member>
 		<member name="sleeping" type="bool" setter="set_sleeping" getter="is_sleeping" default="false">
-			If [code]true[/code], the body will not move and will not calculate forces until woken up by another body through, for example, a collision, or by using the [method apply_impulse] or [method add_force] methods.
+			If [code]true[/code], the body will not move and will not calculate forces until woken up by another body through, for example, a collision, or by using the [method apply_impulse] or [method apply_force] methods.
 		</member>
 	</members>
 	<signals>

+ 48 - 12
doc/classes/RigidDynamicBody3D.xml

@@ -22,28 +22,36 @@
 				Called during physics processing, allowing you to read and safely modify the simulation state for the object. By default, it works in addition to the usual physics behavior, but the [member custom_integrator] property allows you to disable the default behavior and do fully custom force integration for a body.
 			</description>
 		</method>
-		<method name="add_central_force">
+		<method name="add_constant_central_force">
 			<return type="void" />
 			<argument index="0" name="force" type="Vector3" />
 			<description>
-				Adds a constant directional force (i.e. acceleration) without affecting rotation.
-				This is equivalent to [code]add_force(force, Vector3(0,0,0))[/code].
+				Adds a constant directional force without affecting rotation that keeps being applied over time until cleared with [code]constant_force = Vector3(0, 0, 0)[/code].
+				This is equivalent to using [method add_constant_force] at the body's center of mass.
 			</description>
 		</method>
-		<method name="add_force">
+		<method name="add_constant_force">
 			<return type="void" />
 			<argument index="0" name="force" type="Vector3" />
 			<argument index="1" name="position" type="Vector3" default="Vector3(0, 0, 0)" />
 			<description>
-				Adds a constant directional force (i.e. acceleration).
-				The position uses the rotation of the global coordinate system, but is centered at the object's origin.
+				Adds a constant positioned force to the body that keeps being applied over time until cleared with [code]constant_force = Vector3(0, 0, 0)[/code].
+				[code]position[/code] is the offset from the body origin in global coordinates.
 			</description>
 		</method>
-		<method name="add_torque">
+		<method name="add_constant_torque">
 			<return type="void" />
 			<argument index="0" name="torque" type="Vector3" />
 			<description>
-				Adds a constant rotational force (i.e. a motor) without affecting position.
+				Adds a constant rotational force without affecting position that keeps being applied over time until cleared with [code]constant_torque = Vector3(0, 0, 0)[/code].
+			</description>
+		</method>
+		<method name="apply_central_force">
+			<return type="void" />
+			<argument index="0" name="force" type="Vector3" />
+			<description>
+				Applies a directional force without affecting rotation. A force is time dependent and meant to be applied every physics update.
+				This is equivalent to using [method apply_force] at the body's center of mass.
 			</description>
 		</method>
 		<method name="apply_central_impulse">
@@ -51,7 +59,17 @@
 			<argument index="0" name="impulse" type="Vector3" />
 			<description>
 				Applies a directional impulse without affecting rotation.
-				This is equivalent to [code]apply_impulse(Vector3(0,0,0), impulse)[/code].
+				An impulse is time-independent! Applying an impulse every frame would result in a framerate-dependent force. For this reason, it should only be used when simulating one-time impacts (use the "_force" functions otherwise).
+				This is equivalent to using [method apply_impulse] at the body's center of mass.
+			</description>
+		</method>
+		<method name="apply_force">
+			<return type="void" />
+			<argument index="0" name="force" type="Vector3" />
+			<argument index="1" name="position" type="Vector3" default="Vector3(0, 0, 0)" />
+			<description>
+				Applies a positioned force to the body. A force is time dependent and meant to be applied every physics update.
+				[code]position[/code] is the offset from the body origin in global coordinates.
 			</description>
 		</method>
 		<method name="apply_impulse">
@@ -59,14 +77,24 @@
 			<argument index="0" name="impulse" type="Vector3" />
 			<argument index="1" name="position" type="Vector3" default="Vector3(0, 0, 0)" />
 			<description>
-				Applies a positioned impulse to the body. An impulse is time independent! Applying an impulse every frame would result in a framerate-dependent force. For this reason it should only be used when simulating one-time impacts. The position uses the rotation of the global coordinate system, but is centered at the object's origin.
+				Applies a positioned impulse to the body.
+				An impulse is time-independent! Applying an impulse every frame would result in a framerate-dependent force. For this reason, it should only be used when simulating one-time impacts (use the "_force" functions otherwise).
+				[code]position[/code] is the offset from the body origin in global coordinates.
+			</description>
+		</method>
+		<method name="apply_torque">
+			<return type="void" />
+			<argument index="0" name="torque" type="Vector3" />
+			<description>
+				Applies a rotational force without affecting position. A force is time dependent and meant to be applied every physics update.
 			</description>
 		</method>
 		<method name="apply_torque_impulse">
 			<return type="void" />
 			<argument index="0" name="impulse" type="Vector3" />
 			<description>
-				Applies a torque impulse which will be affected by the body mass and shape. This will rotate the body around the [code]impulse[/code] vector passed.
+				Applies a rotational impulse to the body without affecting the position.
+				An impulse is time-independent! Applying an impulse every frame would result in a framerate-dependent force. For this reason, it should only be used when simulating one-time impacts (use the "_force" functions otherwise).
 			</description>
 		</method>
 		<method name="get_colliding_bodies" qualifiers="const">
@@ -111,6 +139,14 @@
 		<member name="center_of_mass_mode" type="int" setter="set_center_of_mass_mode" getter="get_center_of_mass_mode" enum="RigidDynamicBody3D.CenterOfMassMode" default="0">
 			Defines the way the body's center of mass is set. See [enum CenterOfMassMode] for possible values.
 		</member>
+		<member name="constant_force" type="Vector3" setter="set_constant_force" getter="get_constant_force" default="Vector3(0, 0, 0)">
+			The body's total constant positional forces applied during each physics update.
+			See [method add_constant_force] and [method add_constant_central_force].
+		</member>
+		<member name="constant_torque" type="Vector3" setter="set_constant_torque" getter="get_constant_torque" default="Vector3(0, 0, 0)">
+			The body's total constant rotational forces applied during each physics update.
+			See [method add_constant_torque].
+		</member>
 		<member name="contact_monitor" type="bool" setter="set_contact_monitor" getter="is_contact_monitor_enabled" default="false">
 			If [code]true[/code], the RigidDynamicBody3D will emit signals when it collides with another RigidDynamicBody3D. See also [member contacts_reported].
 		</member>
@@ -162,7 +198,7 @@
 			If a material is assigned to this property, it will be used instead of any other physics material, such as an inherited one.
 		</member>
 		<member name="sleeping" type="bool" setter="set_sleeping" getter="is_sleeping" default="false">
-			If [code]true[/code], the body will not move and will not calculate forces until woken up by another body through, for example, a collision, or by using the [method apply_impulse] or [method add_force] methods.
+			If [code]true[/code], the body will not move and will not calculate forces until woken up by another body through, for example, a collision, or by using the [method apply_impulse] or [method apply_force] methods.
 		</member>
 	</members>
 	<signals>

+ 44 - 28
scene/2d/physics_body_2d.cpp

@@ -809,32 +809,44 @@ void RigidDynamicBody2D::apply_torque_impulse(real_t p_torque) {
 	PhysicsServer2D::get_singleton()->body_apply_torque_impulse(get_rid(), p_torque);
 }
 
-void RigidDynamicBody2D::set_applied_force(const Vector2 &p_force) {
-	PhysicsServer2D::get_singleton()->body_set_applied_force(get_rid(), p_force);
-};
+void RigidDynamicBody2D::apply_central_force(const Vector2 &p_force) {
+	PhysicsServer2D::get_singleton()->body_apply_central_force(get_rid(), p_force);
+}
 
-Vector2 RigidDynamicBody2D::get_applied_force() const {
-	return PhysicsServer2D::get_singleton()->body_get_applied_force(get_rid());
-};
+void RigidDynamicBody2D::apply_force(const Vector2 &p_force, const Vector2 &p_position) {
+	PhysicsServer2D::get_singleton()->body_apply_force(get_rid(), p_force, p_position);
+}
 
-void RigidDynamicBody2D::set_applied_torque(const real_t p_torque) {
-	PhysicsServer2D::get_singleton()->body_set_applied_torque(get_rid(), p_torque);
-};
+void RigidDynamicBody2D::apply_torque(real_t p_torque) {
+	PhysicsServer2D::get_singleton()->body_apply_torque(get_rid(), p_torque);
+}
 
-real_t RigidDynamicBody2D::get_applied_torque() const {
-	return PhysicsServer2D::get_singleton()->body_get_applied_torque(get_rid());
-};
+void RigidDynamicBody2D::add_constant_central_force(const Vector2 &p_force) {
+	PhysicsServer2D::get_singleton()->body_add_constant_central_force(get_rid(), p_force);
+}
 
-void RigidDynamicBody2D::add_central_force(const Vector2 &p_force) {
-	PhysicsServer2D::get_singleton()->body_add_central_force(get_rid(), p_force);
+void RigidDynamicBody2D::add_constant_force(const Vector2 &p_force, const Vector2 &p_position) {
+	PhysicsServer2D::get_singleton()->body_add_constant_force(get_rid(), p_force, p_position);
 }
 
-void RigidDynamicBody2D::add_force(const Vector2 &p_force, const Vector2 &p_position) {
-	PhysicsServer2D::get_singleton()->body_add_force(get_rid(), p_force, p_position);
+void RigidDynamicBody2D::add_constant_torque(const real_t p_torque) {
+	PhysicsServer2D::get_singleton()->body_add_constant_torque(get_rid(), p_torque);
 }
 
-void RigidDynamicBody2D::add_torque(const real_t p_torque) {
-	PhysicsServer2D::get_singleton()->body_add_torque(get_rid(), p_torque);
+void RigidDynamicBody2D::set_constant_force(const Vector2 &p_force) {
+	PhysicsServer2D::get_singleton()->body_set_constant_force(get_rid(), p_force);
+}
+
+Vector2 RigidDynamicBody2D::get_constant_force() const {
+	return PhysicsServer2D::get_singleton()->body_get_constant_force(get_rid());
+}
+
+void RigidDynamicBody2D::set_constant_torque(real_t p_torque) {
+	PhysicsServer2D::get_singleton()->body_set_constant_torque(get_rid(), p_torque);
+}
+
+real_t RigidDynamicBody2D::get_constant_torque() const {
+	return PhysicsServer2D::get_singleton()->body_get_constant_torque(get_rid());
 }
 
 void RigidDynamicBody2D::set_continuous_collision_detection_mode(CCDMode p_mode) {
@@ -979,15 +991,19 @@ void RigidDynamicBody2D::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("apply_impulse", "impulse", "position"), &RigidDynamicBody2D::apply_impulse, Vector2());
 	ClassDB::bind_method(D_METHOD("apply_torque_impulse", "torque"), &RigidDynamicBody2D::apply_torque_impulse);
 
-	ClassDB::bind_method(D_METHOD("set_applied_force", "force"), &RigidDynamicBody2D::set_applied_force);
-	ClassDB::bind_method(D_METHOD("get_applied_force"), &RigidDynamicBody2D::get_applied_force);
+	ClassDB::bind_method(D_METHOD("apply_central_force", "force"), &RigidDynamicBody2D::apply_central_force);
+	ClassDB::bind_method(D_METHOD("apply_force", "force", "position"), &RigidDynamicBody2D::apply_force, Vector2());
+	ClassDB::bind_method(D_METHOD("apply_torque", "torque"), &RigidDynamicBody2D::apply_torque);
+
+	ClassDB::bind_method(D_METHOD("add_constant_central_force", "force"), &RigidDynamicBody2D::add_constant_central_force);
+	ClassDB::bind_method(D_METHOD("add_constant_force", "force", "position"), &RigidDynamicBody2D::add_constant_force, Vector2());
+	ClassDB::bind_method(D_METHOD("add_constant_torque", "torque"), &RigidDynamicBody2D::add_constant_torque);
 
-	ClassDB::bind_method(D_METHOD("set_applied_torque", "torque"), &RigidDynamicBody2D::set_applied_torque);
-	ClassDB::bind_method(D_METHOD("get_applied_torque"), &RigidDynamicBody2D::get_applied_torque);
+	ClassDB::bind_method(D_METHOD("set_constant_force", "force"), &RigidDynamicBody2D::set_constant_force);
+	ClassDB::bind_method(D_METHOD("get_constant_force"), &RigidDynamicBody2D::get_constant_force);
 
-	ClassDB::bind_method(D_METHOD("add_central_force", "force"), &RigidDynamicBody2D::add_central_force);
-	ClassDB::bind_method(D_METHOD("add_force", "force", "position"), &RigidDynamicBody2D::add_force, Vector2());
-	ClassDB::bind_method(D_METHOD("add_torque", "torque"), &RigidDynamicBody2D::add_torque);
+	ClassDB::bind_method(D_METHOD("set_constant_torque", "torque"), &RigidDynamicBody2D::set_constant_torque);
+	ClassDB::bind_method(D_METHOD("get_constant_torque"), &RigidDynamicBody2D::get_constant_torque);
 
 	ClassDB::bind_method(D_METHOD("set_sleeping", "sleeping"), &RigidDynamicBody2D::set_sleeping);
 	ClassDB::bind_method(D_METHOD("is_sleeping"), &RigidDynamicBody2D::is_sleeping);
@@ -1032,9 +1048,9 @@ void RigidDynamicBody2D::_bind_methods() {
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_velocity"), "set_angular_velocity", "get_angular_velocity");
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "angular_damp_mode", PROPERTY_HINT_ENUM, "Combine,Replace"), "set_angular_damp_mode", "get_angular_damp_mode");
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater"), "set_angular_damp", "get_angular_damp");
-	ADD_GROUP("Applied Forces", "applied_");
-	ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "applied_force"), "set_applied_force", "get_applied_force");
-	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "applied_torque"), "set_applied_torque", "get_applied_torque");
+	ADD_GROUP("Constant Forces", "constant_");
+	ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "constant_force"), "set_constant_force", "get_constant_force");
+	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "constant_torque"), "set_constant_torque", "get_constant_torque");
 
 	ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape_index"), PropertyInfo(Variant::INT, "local_shape_index")));
 	ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape_index"), PropertyInfo(Variant::INT, "local_shape_index")));

+ 11 - 7
scene/2d/physics_body_2d.h

@@ -292,15 +292,19 @@ public:
 	void apply_impulse(const Vector2 &p_impulse, const Vector2 &p_position = Vector2());
 	void apply_torque_impulse(real_t p_torque);
 
-	void set_applied_force(const Vector2 &p_force);
-	Vector2 get_applied_force() const;
+	void apply_central_force(const Vector2 &p_force);
+	void apply_force(const Vector2 &p_force, const Vector2 &p_position = Vector2());
+	void apply_torque(real_t p_torque);
 
-	void set_applied_torque(const real_t p_torque);
-	real_t get_applied_torque() const;
+	void add_constant_central_force(const Vector2 &p_force);
+	void add_constant_force(const Vector2 &p_force, const Vector2 &p_position = Vector2());
+	void add_constant_torque(real_t p_torque);
 
-	void add_central_force(const Vector2 &p_force);
-	void add_force(const Vector2 &p_force, const Vector2 &p_position = Vector2());
-	void add_torque(real_t p_torque);
+	void set_constant_force(const Vector2 &p_force);
+	Vector2 get_constant_force() const;
+
+	void set_constant_torque(real_t p_torque);
+	real_t get_constant_torque() const;
 
 	TypedArray<Node2D> get_colliding_bodies() const; //function for script
 

+ 58 - 16
scene/3d/physics_body_3d.cpp

@@ -875,30 +875,59 @@ int RigidDynamicBody3D::get_max_contacts_reported() const {
 	return max_contacts_reported;
 }
 
-void RigidDynamicBody3D::add_central_force(const Vector3 &p_force) {
-	PhysicsServer3D::get_singleton()->body_add_central_force(get_rid(), p_force);
+void RigidDynamicBody3D::apply_central_impulse(const Vector3 &p_impulse) {
+	PhysicsServer3D::get_singleton()->body_apply_central_impulse(get_rid(), p_impulse);
 }
 
-void RigidDynamicBody3D::add_force(const Vector3 &p_force, const Vector3 &p_position) {
+void RigidDynamicBody3D::apply_impulse(const Vector3 &p_impulse, const Vector3 &p_position) {
 	PhysicsServer3D *singleton = PhysicsServer3D::get_singleton();
-	singleton->body_add_force(get_rid(), p_force, p_position);
+	singleton->body_apply_impulse(get_rid(), p_impulse, p_position);
 }
 
-void RigidDynamicBody3D::add_torque(const Vector3 &p_torque) {
-	PhysicsServer3D::get_singleton()->body_add_torque(get_rid(), p_torque);
+void RigidDynamicBody3D::apply_torque_impulse(const Vector3 &p_impulse) {
+	PhysicsServer3D::get_singleton()->body_apply_torque_impulse(get_rid(), p_impulse);
 }
 
-void RigidDynamicBody3D::apply_central_impulse(const Vector3 &p_impulse) {
-	PhysicsServer3D::get_singleton()->body_apply_central_impulse(get_rid(), p_impulse);
+void RigidDynamicBody3D::apply_central_force(const Vector3 &p_force) {
+	PhysicsServer3D::get_singleton()->body_apply_central_force(get_rid(), p_force);
 }
 
-void RigidDynamicBody3D::apply_impulse(const Vector3 &p_impulse, const Vector3 &p_position) {
+void RigidDynamicBody3D::apply_force(const Vector3 &p_force, const Vector3 &p_position) {
 	PhysicsServer3D *singleton = PhysicsServer3D::get_singleton();
-	singleton->body_apply_impulse(get_rid(), p_impulse, p_position);
+	singleton->body_apply_force(get_rid(), p_force, p_position);
 }
 
-void RigidDynamicBody3D::apply_torque_impulse(const Vector3 &p_impulse) {
-	PhysicsServer3D::get_singleton()->body_apply_torque_impulse(get_rid(), p_impulse);
+void RigidDynamicBody3D::apply_torque(const Vector3 &p_torque) {
+	PhysicsServer3D::get_singleton()->body_apply_torque(get_rid(), p_torque);
+}
+
+void RigidDynamicBody3D::add_constant_central_force(const Vector3 &p_force) {
+	PhysicsServer3D::get_singleton()->body_add_constant_central_force(get_rid(), p_force);
+}
+
+void RigidDynamicBody3D::add_constant_force(const Vector3 &p_force, const Vector3 &p_position) {
+	PhysicsServer3D *singleton = PhysicsServer3D::get_singleton();
+	singleton->body_add_constant_force(get_rid(), p_force, p_position);
+}
+
+void RigidDynamicBody3D::add_constant_torque(const Vector3 &p_torque) {
+	PhysicsServer3D::get_singleton()->body_add_constant_torque(get_rid(), p_torque);
+}
+
+void RigidDynamicBody3D::set_constant_force(const Vector3 &p_force) {
+	PhysicsServer3D::get_singleton()->body_set_constant_force(get_rid(), p_force);
+}
+
+Vector3 RigidDynamicBody3D::get_constant_force() const {
+	return PhysicsServer3D::get_singleton()->body_get_constant_force(get_rid());
+}
+
+void RigidDynamicBody3D::set_constant_torque(const Vector3 &p_torque) {
+	PhysicsServer3D::get_singleton()->body_set_constant_torque(get_rid(), p_torque);
+}
+
+Vector3 RigidDynamicBody3D::get_constant_torque() const {
+	return PhysicsServer3D::get_singleton()->body_get_constant_torque(get_rid());
 }
 
 void RigidDynamicBody3D::set_use_continuous_collision_detection(bool p_enable) {
@@ -1024,14 +1053,24 @@ void RigidDynamicBody3D::_bind_methods() {
 
 	ClassDB::bind_method(D_METHOD("set_axis_velocity", "axis_velocity"), &RigidDynamicBody3D::set_axis_velocity);
 
-	ClassDB::bind_method(D_METHOD("add_central_force", "force"), &RigidDynamicBody3D::add_central_force);
-	ClassDB::bind_method(D_METHOD("add_force", "force", "position"), &RigidDynamicBody3D::add_force, Vector3());
-	ClassDB::bind_method(D_METHOD("add_torque", "torque"), &RigidDynamicBody3D::add_torque);
-
 	ClassDB::bind_method(D_METHOD("apply_central_impulse", "impulse"), &RigidDynamicBody3D::apply_central_impulse);
 	ClassDB::bind_method(D_METHOD("apply_impulse", "impulse", "position"), &RigidDynamicBody3D::apply_impulse, Vector3());
 	ClassDB::bind_method(D_METHOD("apply_torque_impulse", "impulse"), &RigidDynamicBody3D::apply_torque_impulse);
 
+	ClassDB::bind_method(D_METHOD("apply_central_force", "force"), &RigidDynamicBody3D::apply_central_force);
+	ClassDB::bind_method(D_METHOD("apply_force", "force", "position"), &RigidDynamicBody3D::apply_force, Vector3());
+	ClassDB::bind_method(D_METHOD("apply_torque", "torque"), &RigidDynamicBody3D::apply_torque);
+
+	ClassDB::bind_method(D_METHOD("add_constant_central_force", "force"), &RigidDynamicBody3D::add_constant_central_force);
+	ClassDB::bind_method(D_METHOD("add_constant_force", "force", "position"), &RigidDynamicBody3D::add_constant_force, Vector3());
+	ClassDB::bind_method(D_METHOD("add_constant_torque", "torque"), &RigidDynamicBody3D::add_constant_torque);
+
+	ClassDB::bind_method(D_METHOD("set_constant_force", "force"), &RigidDynamicBody3D::set_constant_force);
+	ClassDB::bind_method(D_METHOD("get_constant_force"), &RigidDynamicBody3D::get_constant_force);
+
+	ClassDB::bind_method(D_METHOD("set_constant_torque", "torque"), &RigidDynamicBody3D::set_constant_torque);
+	ClassDB::bind_method(D_METHOD("get_constant_torque"), &RigidDynamicBody3D::get_constant_torque);
+
 	ClassDB::bind_method(D_METHOD("set_sleeping", "sleeping"), &RigidDynamicBody3D::set_sleeping);
 	ClassDB::bind_method(D_METHOD("is_sleeping"), &RigidDynamicBody3D::is_sleeping);
 
@@ -1075,6 +1114,9 @@ void RigidDynamicBody3D::_bind_methods() {
 	ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "angular_velocity"), "set_angular_velocity", "get_angular_velocity");
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "angular_damp_mode", PROPERTY_HINT_ENUM, "Combine,Replace"), "set_angular_damp_mode", "get_angular_damp_mode");
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), "set_angular_damp", "get_angular_damp");
+	ADD_GROUP("Constant Forces", "constant_");
+	ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "constant_force"), "set_constant_force", "get_constant_force");
+	ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "constant_torque"), "set_constant_torque", "get_constant_torque");
 
 	ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape_index"), PropertyInfo(Variant::INT, "local_shape_index")));
 	ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape_index"), PropertyInfo(Variant::INT, "local_shape_index")));

+ 14 - 4
scene/3d/physics_body_3d.h

@@ -306,14 +306,24 @@ public:
 
 	Array get_colliding_bodies() const;
 
-	void add_central_force(const Vector3 &p_force);
-	void add_force(const Vector3 &p_force, const Vector3 &p_position = Vector3());
-	void add_torque(const Vector3 &p_torque);
-
 	void apply_central_impulse(const Vector3 &p_impulse);
 	void apply_impulse(const Vector3 &p_impulse, const Vector3 &p_position = Vector3());
 	void apply_torque_impulse(const Vector3 &p_impulse);
 
+	void apply_central_force(const Vector3 &p_force);
+	void apply_force(const Vector3 &p_force, const Vector3 &p_position = Vector3());
+	void apply_torque(const Vector3 &p_torque);
+
+	void add_constant_central_force(const Vector3 &p_force);
+	void add_constant_force(const Vector3 &p_force, const Vector3 &p_position = Vector3());
+	void add_constant_torque(const Vector3 &p_torque);
+
+	void set_constant_force(const Vector3 &p_force);
+	Vector3 get_constant_force() const;
+
+	void set_constant_torque(const Vector3 &p_torque);
+	Vector3 get_constant_torque() const;
+
 	virtual TypedArray<String> get_configuration_warnings() const override;
 
 	RigidDynamicBody3D();

+ 6 - 4
servers/physics_2d/godot_body_2d.cpp

@@ -569,9 +569,8 @@ void GodotBody2D::integrate_forces(real_t p_step) {
 		if (!omit_force_integration) {
 			//overridden by direct state query
 
-			Vector2 force = gravity * mass;
-			force += applied_force;
-			real_t torque = applied_torque;
+			Vector2 force = gravity * mass + applied_force + constant_force;
+			real_t torque = applied_torque + constant_torque;
 
 			real_t damp = 1.0 - p_step * total_linear_damp;
 
@@ -598,7 +597,10 @@ void GodotBody2D::integrate_forces(real_t p_step) {
 		}
 	}
 
-	biased_angular_velocity = 0;
+	applied_force = Vector2();
+	applied_torque = 0.0;
+
+	biased_angular_velocity = 0.0;
 	biased_linear_velocity = Vector2();
 
 	if (do_motion) { //shapes temporarily extend for raycast

+ 35 - 19
servers/physics_2d/godot_body_2d.h

@@ -89,6 +89,9 @@ class GodotBody2D : public GodotCollisionObject2D {
 	Vector2 applied_force;
 	real_t applied_torque = 0.0;
 
+	Vector2 constant_force;
+	real_t constant_torque = 0.0;
+
 	SelfList<GodotBody2D> active_list;
 	SelfList<GodotBody2D> mass_properties_update_list;
 	SelfList<GodotBody2D> direct_state_query_list;
@@ -245,6 +248,38 @@ public:
 		}
 	}
 
+	_FORCE_INLINE_ void apply_central_force(const Vector2 &p_force) {
+		applied_force += p_force;
+	}
+
+	_FORCE_INLINE_ void apply_force(const Vector2 &p_force, const Vector2 &p_position = Vector2()) {
+		applied_force += p_force;
+		applied_torque += (p_position - center_of_mass).cross(p_force);
+	}
+
+	_FORCE_INLINE_ void apply_torque(real_t p_torque) {
+		applied_torque += p_torque;
+	}
+
+	_FORCE_INLINE_ void add_constant_central_force(const Vector2 &p_force) {
+		constant_force += p_force;
+	}
+
+	_FORCE_INLINE_ void add_constant_force(const Vector2 &p_force, const Vector2 &p_position = Vector2()) {
+		constant_force += p_force;
+		constant_torque += (p_position - center_of_mass).cross(p_force);
+	}
+
+	_FORCE_INLINE_ void add_constant_torque(real_t p_torque) {
+		constant_torque += p_torque;
+	}
+
+	void set_constant_force(const Vector2 &p_force) { constant_force = p_force; }
+	Vector2 get_constant_force() const { return constant_force; }
+
+	void set_constant_torque(real_t p_torque) { constant_torque = p_torque; }
+	real_t get_constant_torque() const { return constant_torque; }
+
 	void set_active(bool p_active);
 	_FORCE_INLINE_ bool is_active() const { return active; }
 
@@ -264,25 +299,6 @@ public:
 	void set_state(PhysicsServer2D::BodyState p_state, const Variant &p_variant);
 	Variant get_state(PhysicsServer2D::BodyState p_state) const;
 
-	void set_applied_force(const Vector2 &p_force) { applied_force = p_force; }
-	Vector2 get_applied_force() const { return applied_force; }
-
-	void set_applied_torque(real_t p_torque) { applied_torque = p_torque; }
-	real_t get_applied_torque() const { return applied_torque; }
-
-	_FORCE_INLINE_ void add_central_force(const Vector2 &p_force) {
-		applied_force += p_force;
-	}
-
-	_FORCE_INLINE_ void add_force(const Vector2 &p_force, const Vector2 &p_position = Vector2()) {
-		applied_force += p_force;
-		applied_torque += (p_position - center_of_mass).cross(p_force);
-	}
-
-	_FORCE_INLINE_ void add_torque(real_t p_torque) {
-		applied_torque += p_torque;
-	}
-
 	_FORCE_INLINE_ void set_continuous_collision_detection_mode(PhysicsServer2D::CCDMode p_mode) { continuous_cd_mode = p_mode; }
 	_FORCE_INLINE_ PhysicsServer2D::CCDMode get_continuous_collision_detection_mode() const { return continuous_cd_mode; }
 

+ 49 - 12
servers/physics_2d/godot_body_direct_state_2d.cpp

@@ -92,34 +92,71 @@ Vector2 GodotPhysicsDirectBodyState2D::get_velocity_at_local_position(const Vect
 	return body->get_velocity_in_local_point(p_position);
 }
 
-void GodotPhysicsDirectBodyState2D::add_central_force(const Vector2 &p_force) {
+void GodotPhysicsDirectBodyState2D::apply_central_impulse(const Vector2 &p_impulse) {
 	body->wakeup();
-	body->add_central_force(p_force);
+	body->apply_central_impulse(p_impulse);
 }
 
-void GodotPhysicsDirectBodyState2D::add_force(const Vector2 &p_force, const Vector2 &p_position) {
+void GodotPhysicsDirectBodyState2D::apply_impulse(const Vector2 &p_impulse, const Vector2 &p_position) {
 	body->wakeup();
-	body->add_force(p_force, p_position);
+	body->apply_impulse(p_impulse, p_position);
 }
 
-void GodotPhysicsDirectBodyState2D::add_torque(real_t p_torque) {
+void GodotPhysicsDirectBodyState2D::apply_torque_impulse(real_t p_torque) {
 	body->wakeup();
-	body->add_torque(p_torque);
+	body->apply_torque_impulse(p_torque);
 }
 
-void GodotPhysicsDirectBodyState2D::apply_central_impulse(const Vector2 &p_impulse) {
+void GodotPhysicsDirectBodyState2D::apply_central_force(const Vector2 &p_force) {
 	body->wakeup();
-	body->apply_central_impulse(p_impulse);
+	body->apply_central_force(p_force);
 }
 
-void GodotPhysicsDirectBodyState2D::apply_impulse(const Vector2 &p_impulse, const Vector2 &p_position) {
+void GodotPhysicsDirectBodyState2D::apply_force(const Vector2 &p_force, const Vector2 &p_position) {
 	body->wakeup();
-	body->apply_impulse(p_impulse, p_position);
+	body->apply_force(p_force, p_position);
 }
 
-void GodotPhysicsDirectBodyState2D::apply_torque_impulse(real_t p_torque) {
+void GodotPhysicsDirectBodyState2D::apply_torque(real_t p_torque) {
 	body->wakeup();
-	body->apply_torque_impulse(p_torque);
+	body->apply_torque(p_torque);
+}
+
+void GodotPhysicsDirectBodyState2D::add_constant_central_force(const Vector2 &p_force) {
+	body->wakeup();
+	body->add_constant_central_force(p_force);
+}
+
+void GodotPhysicsDirectBodyState2D::add_constant_force(const Vector2 &p_force, const Vector2 &p_position) {
+	body->wakeup();
+	body->add_constant_force(p_force, p_position);
+}
+
+void GodotPhysicsDirectBodyState2D::add_constant_torque(real_t p_torque) {
+	body->wakeup();
+	body->add_constant_torque(p_torque);
+}
+
+void GodotPhysicsDirectBodyState2D::set_constant_force(const Vector2 &p_force) {
+	if (!p_force.is_equal_approx(Vector2())) {
+		body->wakeup();
+	}
+	body->set_constant_force(p_force);
+}
+
+Vector2 GodotPhysicsDirectBodyState2D::get_constant_force() const {
+	return body->get_constant_force();
+}
+
+void GodotPhysicsDirectBodyState2D::set_constant_torque(real_t p_torque) {
+	if (!Math::is_zero_approx(p_torque)) {
+		body->wakeup();
+	}
+	body->set_constant_torque(p_torque);
+}
+
+real_t GodotPhysicsDirectBodyState2D::get_constant_torque() const {
+	return body->get_constant_torque();
 }
 
 void GodotPhysicsDirectBodyState2D::set_sleep_state(bool p_enable) {

+ 14 - 3
servers/physics_2d/godot_body_direct_state_2d.h

@@ -61,13 +61,24 @@ public:
 
 	virtual Vector2 get_velocity_at_local_position(const Vector2 &p_position) const override;
 
-	virtual void add_central_force(const Vector2 &p_force) override;
-	virtual void add_force(const Vector2 &p_force, const Vector2 &p_position = Vector2()) override;
-	virtual void add_torque(real_t p_torque) override;
 	virtual void apply_central_impulse(const Vector2 &p_impulse) override;
 	virtual void apply_impulse(const Vector2 &p_impulse, const Vector2 &p_position = Vector2()) override;
 	virtual void apply_torque_impulse(real_t p_torque) override;
 
+	virtual void apply_central_force(const Vector2 &p_force) override;
+	virtual void apply_force(const Vector2 &p_force, const Vector2 &p_position = Vector2()) override;
+	virtual void apply_torque(real_t p_torque) override;
+
+	virtual void add_constant_central_force(const Vector2 &p_force) override;
+	virtual void add_constant_force(const Vector2 &p_force, const Vector2 &p_position = Vector2()) override;
+	virtual void add_constant_torque(real_t p_torque) override;
+
+	virtual void set_constant_force(const Vector2 &p_force) override;
+	virtual Vector2 get_constant_force() const override;
+
+	virtual void set_constant_torque(real_t p_torque) override;
+	virtual real_t get_constant_torque() const override;
+
 	virtual void set_sleep_state(bool p_enable) override;
 	virtual bool is_sleeping() const override;
 

+ 75 - 47
servers/physics_2d/godot_physics_server_2d.cpp

@@ -669,68 +669,68 @@ void GodotPhysicsServer2D::body_attach_object_instance_id(RID p_body, ObjectID p
 	ERR_FAIL_COND(!body);
 
 	body->set_instance_id(p_id);
-};
+}
 
 ObjectID GodotPhysicsServer2D::body_get_object_instance_id(RID p_body) const {
 	GodotBody2D *body = body_owner.get_or_null(p_body);
 	ERR_FAIL_COND_V(!body, ObjectID());
 
 	return body->get_instance_id();
-};
+}
 
 void GodotPhysicsServer2D::body_attach_canvas_instance_id(RID p_body, ObjectID p_id) {
 	GodotBody2D *body = body_owner.get_or_null(p_body);
 	ERR_FAIL_COND(!body);
 
 	body->set_canvas_instance_id(p_id);
-};
+}
 
 ObjectID GodotPhysicsServer2D::body_get_canvas_instance_id(RID p_body) const {
 	GodotBody2D *body = body_owner.get_or_null(p_body);
 	ERR_FAIL_COND_V(!body, ObjectID());
 
 	return body->get_canvas_instance_id();
-};
+}
 
 void GodotPhysicsServer2D::body_set_collision_layer(RID p_body, uint32_t p_layer) {
 	GodotBody2D *body = body_owner.get_or_null(p_body);
 	ERR_FAIL_COND(!body);
 	body->set_collision_layer(p_layer);
-};
+}
 
 uint32_t GodotPhysicsServer2D::body_get_collision_layer(RID p_body) const {
 	GodotBody2D *body = body_owner.get_or_null(p_body);
 	ERR_FAIL_COND_V(!body, 0);
 
 	return body->get_collision_layer();
-};
+}
 
 void GodotPhysicsServer2D::body_set_collision_mask(RID p_body, uint32_t p_mask) {
 	GodotBody2D *body = body_owner.get_or_null(p_body);
 	ERR_FAIL_COND(!body);
 	body->set_collision_mask(p_mask);
-};
+}
 
 uint32_t GodotPhysicsServer2D::body_get_collision_mask(RID p_body) const {
 	GodotBody2D *body = body_owner.get_or_null(p_body);
 	ERR_FAIL_COND_V(!body, 0);
 
 	return body->get_collision_mask();
-};
+}
 
 void GodotPhysicsServer2D::body_set_param(RID p_body, BodyParameter p_param, const Variant &p_value) {
 	GodotBody2D *body = body_owner.get_or_null(p_body);
 	ERR_FAIL_COND(!body);
 
 	body->set_param(p_param, p_value);
-};
+}
 
 Variant GodotPhysicsServer2D::body_get_param(RID p_body, BodyParameter p_param) const {
 	GodotBody2D *body = body_owner.get_or_null(p_body);
 	ERR_FAIL_COND_V(!body, 0);
 
 	return body->get_param(p_param);
-};
+}
 
 void GodotPhysicsServer2D::body_reset_mass_properties(RID p_body) {
 	GodotBody2D *body = body_owner.get_or_null(p_body);
@@ -744,95 +744,123 @@ void GodotPhysicsServer2D::body_set_state(RID p_body, BodyState p_state, const V
 	ERR_FAIL_COND(!body);
 
 	body->set_state(p_state, p_variant);
-};
+}
 
 Variant GodotPhysicsServer2D::body_get_state(RID p_body, BodyState p_state) const {
 	GodotBody2D *body = body_owner.get_or_null(p_body);
 	ERR_FAIL_COND_V(!body, Variant());
 
 	return body->get_state(p_state);
-};
+}
 
-void GodotPhysicsServer2D::body_set_applied_force(RID p_body, const Vector2 &p_force) {
+void GodotPhysicsServer2D::body_apply_central_impulse(RID p_body, const Vector2 &p_impulse) {
 	GodotBody2D *body = body_owner.get_or_null(p_body);
 	ERR_FAIL_COND(!body);
 
-	body->set_applied_force(p_force);
+	body->apply_central_impulse(p_impulse);
 	body->wakeup();
-};
+}
 
-Vector2 GodotPhysicsServer2D::body_get_applied_force(RID p_body) const {
+void GodotPhysicsServer2D::body_apply_torque_impulse(RID p_body, real_t p_torque) {
 	GodotBody2D *body = body_owner.get_or_null(p_body);
-	ERR_FAIL_COND_V(!body, Vector2());
-	return body->get_applied_force();
-};
+	ERR_FAIL_COND(!body);
 
-void GodotPhysicsServer2D::body_set_applied_torque(RID p_body, real_t p_torque) {
+	_update_shapes();
+
+	body->apply_torque_impulse(p_torque);
+	body->wakeup();
+}
+
+void GodotPhysicsServer2D::body_apply_impulse(RID p_body, const Vector2 &p_impulse, const Vector2 &p_position) {
 	GodotBody2D *body = body_owner.get_or_null(p_body);
 	ERR_FAIL_COND(!body);
 
-	body->set_applied_torque(p_torque);
+	_update_shapes();
+
+	body->apply_impulse(p_impulse, p_position);
 	body->wakeup();
-};
+}
 
-real_t GodotPhysicsServer2D::body_get_applied_torque(RID p_body) const {
+void GodotPhysicsServer2D::body_apply_central_force(RID p_body, const Vector2 &p_force) {
 	GodotBody2D *body = body_owner.get_or_null(p_body);
-	ERR_FAIL_COND_V(!body, 0);
+	ERR_FAIL_COND(!body);
 
-	return body->get_applied_torque();
-};
+	body->apply_central_force(p_force);
+	body->wakeup();
+}
 
-void GodotPhysicsServer2D::body_apply_central_impulse(RID p_body, const Vector2 &p_impulse) {
+void GodotPhysicsServer2D::body_apply_force(RID p_body, const Vector2 &p_force, const Vector2 &p_position) {
 	GodotBody2D *body = body_owner.get_or_null(p_body);
 	ERR_FAIL_COND(!body);
 
-	body->apply_central_impulse(p_impulse);
+	body->apply_force(p_force, p_position);
 	body->wakeup();
 }
 
-void GodotPhysicsServer2D::body_apply_torque_impulse(RID p_body, real_t p_torque) {
+void GodotPhysicsServer2D::body_apply_torque(RID p_body, real_t p_torque) {
 	GodotBody2D *body = body_owner.get_or_null(p_body);
 	ERR_FAIL_COND(!body);
 
-	_update_shapes();
-
-	body->apply_torque_impulse(p_torque);
+	body->apply_torque(p_torque);
 	body->wakeup();
 }
 
-void GodotPhysicsServer2D::body_apply_impulse(RID p_body, const Vector2 &p_impulse, const Vector2 &p_position) {
+void GodotPhysicsServer2D::body_add_constant_central_force(RID p_body, const Vector2 &p_force) {
 	GodotBody2D *body = body_owner.get_or_null(p_body);
 	ERR_FAIL_COND(!body);
 
-	_update_shapes();
-
-	body->apply_impulse(p_impulse, p_position);
+	body->add_constant_central_force(p_force);
 	body->wakeup();
-};
+}
 
-void GodotPhysicsServer2D::body_add_central_force(RID p_body, const Vector2 &p_force) {
+void GodotPhysicsServer2D::body_add_constant_force(RID p_body, const Vector2 &p_force, const Vector2 &p_position) {
 	GodotBody2D *body = body_owner.get_or_null(p_body);
 	ERR_FAIL_COND(!body);
 
-	body->add_central_force(p_force);
+	body->add_constant_force(p_force, p_position);
 	body->wakeup();
-};
+}
 
-void GodotPhysicsServer2D::body_add_force(RID p_body, const Vector2 &p_force, const Vector2 &p_position) {
+void GodotPhysicsServer2D::body_add_constant_torque(RID p_body, real_t p_torque) {
 	GodotBody2D *body = body_owner.get_or_null(p_body);
 	ERR_FAIL_COND(!body);
 
-	body->add_force(p_force, p_position);
+	body->add_constant_torque(p_torque);
 	body->wakeup();
-};
+}
 
-void GodotPhysicsServer2D::body_add_torque(RID p_body, real_t p_torque) {
+void GodotPhysicsServer2D::body_set_constant_force(RID p_body, const Vector2 &p_force) {
 	GodotBody2D *body = body_owner.get_or_null(p_body);
 	ERR_FAIL_COND(!body);
 
-	body->add_torque(p_torque);
-	body->wakeup();
-};
+	body->set_constant_force(p_force);
+	if (!p_force.is_equal_approx(Vector2())) {
+		body->wakeup();
+	}
+}
+
+Vector2 GodotPhysicsServer2D::body_get_constant_force(RID p_body) const {
+	GodotBody2D *body = body_owner.get_or_null(p_body);
+	ERR_FAIL_COND_V(!body, Vector2());
+	return body->get_constant_force();
+}
+
+void GodotPhysicsServer2D::body_set_constant_torque(RID p_body, real_t p_torque) {
+	GodotBody2D *body = body_owner.get_or_null(p_body);
+	ERR_FAIL_COND(!body);
+
+	body->set_constant_torque(p_torque);
+	if (!Math::is_zero_approx(p_torque)) {
+		body->wakeup();
+	}
+}
+
+real_t GodotPhysicsServer2D::body_get_constant_torque(RID p_body) const {
+	GodotBody2D *body = body_owner.get_or_null(p_body);
+	ERR_FAIL_COND_V(!body, 0);
+
+	return body->get_constant_torque();
+}
 
 void GodotPhysicsServer2D::body_set_axis_velocity(RID p_body, const Vector2 &p_axis_velocity) {
 	GodotBody2D *body = body_owner.get_or_null(p_body);

+ 15 - 10
servers/physics_2d/godot_physics_server_2d.h

@@ -207,19 +207,24 @@ public:
 	virtual void body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) override;
 	virtual Variant body_get_state(RID p_body, BodyState p_state) const override;
 
-	virtual void body_set_applied_force(RID p_body, const Vector2 &p_force) override;
-	virtual Vector2 body_get_applied_force(RID p_body) const override;
-
-	virtual void body_set_applied_torque(RID p_body, real_t p_torque) override;
-	virtual real_t body_get_applied_torque(RID p_body) const override;
-
-	virtual void body_add_central_force(RID p_body, const Vector2 &p_force) override;
-	virtual void body_add_force(RID p_body, const Vector2 &p_force, const Vector2 &p_position = Vector2()) override;
-	virtual void body_add_torque(RID p_body, real_t p_torque) override;
-
 	virtual void body_apply_central_impulse(RID p_body, const Vector2 &p_impulse) override;
 	virtual void body_apply_torque_impulse(RID p_body, real_t p_torque) override;
 	virtual void body_apply_impulse(RID p_body, const Vector2 &p_impulse, const Vector2 &p_position = Vector2()) override;
+
+	virtual void body_apply_central_force(RID p_body, const Vector2 &p_force) override;
+	virtual void body_apply_force(RID p_body, const Vector2 &p_force, const Vector2 &p_position = Vector2()) override;
+	virtual void body_apply_torque(RID p_body, real_t p_torque) override;
+
+	virtual void body_add_constant_central_force(RID p_body, const Vector2 &p_force) override;
+	virtual void body_add_constant_force(RID p_body, const Vector2 &p_force, const Vector2 &p_position = Vector2()) override;
+	virtual void body_add_constant_torque(RID p_body, real_t p_torque) override;
+
+	virtual void body_set_constant_force(RID p_body, const Vector2 &p_force) override;
+	virtual Vector2 body_get_constant_force(RID p_body) const override;
+
+	virtual void body_set_constant_torque(RID p_body, real_t p_torque) override;
+	virtual real_t body_get_constant_torque(RID p_body) const override;
+
 	virtual void body_set_axis_velocity(RID p_body, const Vector2 &p_axis_velocity) override;
 
 	virtual void body_add_collision_exception(RID p_body, RID p_body_b) override;

+ 2 - 3
servers/physics_3d/godot_body_3d.cpp

@@ -628,9 +628,8 @@ void GodotBody3D::integrate_forces(real_t p_step) {
 		if (!omit_force_integration) {
 			//overridden by direct state query
 
-			Vector3 force = gravity * mass;
-			force += applied_force;
-			Vector3 torque = applied_torque;
+			Vector3 force = gravity * mass + applied_force + constant_force;
+			Vector3 torque = applied_torque + constant_torque;
 
 			real_t damp = 1.0 - p_step * total_linear_damp;
 

+ 25 - 9
servers/physics_3d/godot_body_3d.h

@@ -93,6 +93,9 @@ class GodotBody3D : public GodotCollisionObject3D {
 	Vector3 applied_force;
 	Vector3 applied_torque;
 
+	Vector3 constant_force;
+	Vector3 constant_torque;
+
 	SelfList<GodotBody3D> active_list;
 	SelfList<GodotBody3D> mass_properties_update_list;
 	SelfList<GodotBody3D> direct_state_query_list;
@@ -244,19 +247,38 @@ public:
 		biased_angular_velocity += _inv_inertia_tensor.xform(p_impulse);
 	}
 
-	_FORCE_INLINE_ void add_central_force(const Vector3 &p_force) {
+	_FORCE_INLINE_ void apply_central_force(const Vector3 &p_force) {
 		applied_force += p_force;
 	}
 
-	_FORCE_INLINE_ void add_force(const Vector3 &p_force, const Vector3 &p_position = Vector3()) {
+	_FORCE_INLINE_ void apply_force(const Vector3 &p_force, const Vector3 &p_position = Vector3()) {
 		applied_force += p_force;
 		applied_torque += (p_position - center_of_mass).cross(p_force);
 	}
 
-	_FORCE_INLINE_ void add_torque(const Vector3 &p_torque) {
+	_FORCE_INLINE_ void apply_torque(const Vector3 &p_torque) {
 		applied_torque += p_torque;
 	}
 
+	_FORCE_INLINE_ void add_constant_central_force(const Vector3 &p_force) {
+		constant_force += p_force;
+	}
+
+	_FORCE_INLINE_ void add_constant_force(const Vector3 &p_force, const Vector3 &p_position = Vector3()) {
+		constant_force += p_force;
+		constant_torque += (p_position - center_of_mass).cross(p_force);
+	}
+
+	_FORCE_INLINE_ void add_constant_torque(const Vector3 &p_torque) {
+		constant_torque += p_torque;
+	}
+
+	void set_constant_force(const Vector3 &p_force) { constant_force = p_force; }
+	Vector3 get_constant_force() const { return constant_force; }
+
+	void set_constant_torque(const Vector3 &p_torque) { constant_torque = p_torque; }
+	Vector3 get_constant_torque() const { return constant_torque; }
+
 	void set_active(bool p_active);
 	_FORCE_INLINE_ bool is_active() const { return active; }
 
@@ -276,12 +298,6 @@ public:
 	void set_state(PhysicsServer3D::BodyState p_state, const Variant &p_variant);
 	Variant get_state(PhysicsServer3D::BodyState p_state) const;
 
-	void set_applied_force(const Vector3 &p_force) { applied_force = p_force; }
-	Vector3 get_applied_force() const { return applied_force; }
-
-	void set_applied_torque(const Vector3 &p_torque) { applied_torque = p_torque; }
-	Vector3 get_applied_torque() const { return applied_torque; }
-
 	_FORCE_INLINE_ void set_continuous_collision_detection(bool p_enable) { continuous_cd = p_enable; }
 	_FORCE_INLINE_ bool is_continuous_collision_detection_enabled() const { return continuous_cd; }
 

+ 49 - 12
servers/physics_3d/godot_body_direct_state_3d.cpp

@@ -99,34 +99,71 @@ Vector3 GodotPhysicsDirectBodyState3D::get_velocity_at_local_position(const Vect
 	return body->get_velocity_in_local_point(p_position);
 }
 
-void GodotPhysicsDirectBodyState3D::add_central_force(const Vector3 &p_force) {
+void GodotPhysicsDirectBodyState3D::apply_central_impulse(const Vector3 &p_impulse) {
 	body->wakeup();
-	body->add_central_force(p_force);
+	body->apply_central_impulse(p_impulse);
 }
 
-void GodotPhysicsDirectBodyState3D::add_force(const Vector3 &p_force, const Vector3 &p_position) {
+void GodotPhysicsDirectBodyState3D::apply_impulse(const Vector3 &p_impulse, const Vector3 &p_position) {
 	body->wakeup();
-	body->add_force(p_force, p_position);
+	body->apply_impulse(p_impulse, p_position);
 }
 
-void GodotPhysicsDirectBodyState3D::add_torque(const Vector3 &p_torque) {
+void GodotPhysicsDirectBodyState3D::apply_torque_impulse(const Vector3 &p_impulse) {
 	body->wakeup();
-	body->add_torque(p_torque);
+	body->apply_torque_impulse(p_impulse);
 }
 
-void GodotPhysicsDirectBodyState3D::apply_central_impulse(const Vector3 &p_impulse) {
+void GodotPhysicsDirectBodyState3D::apply_central_force(const Vector3 &p_force) {
 	body->wakeup();
-	body->apply_central_impulse(p_impulse);
+	body->apply_central_force(p_force);
 }
 
-void GodotPhysicsDirectBodyState3D::apply_impulse(const Vector3 &p_impulse, const Vector3 &p_position) {
+void GodotPhysicsDirectBodyState3D::apply_force(const Vector3 &p_force, const Vector3 &p_position) {
 	body->wakeup();
-	body->apply_impulse(p_impulse, p_position);
+	body->apply_force(p_force, p_position);
 }
 
-void GodotPhysicsDirectBodyState3D::apply_torque_impulse(const Vector3 &p_impulse) {
+void GodotPhysicsDirectBodyState3D::apply_torque(const Vector3 &p_torque) {
 	body->wakeup();
-	body->apply_torque_impulse(p_impulse);
+	body->apply_torque(p_torque);
+}
+
+void GodotPhysicsDirectBodyState3D::add_constant_central_force(const Vector3 &p_force) {
+	body->wakeup();
+	body->add_constant_central_force(p_force);
+}
+
+void GodotPhysicsDirectBodyState3D::add_constant_force(const Vector3 &p_force, const Vector3 &p_position) {
+	body->wakeup();
+	body->add_constant_force(p_force, p_position);
+}
+
+void GodotPhysicsDirectBodyState3D::add_constant_torque(const Vector3 &p_torque) {
+	body->wakeup();
+	body->add_constant_torque(p_torque);
+}
+
+void GodotPhysicsDirectBodyState3D::set_constant_force(const Vector3 &p_force) {
+	if (!p_force.is_equal_approx(Vector3())) {
+		body->wakeup();
+	}
+	body->set_constant_force(p_force);
+}
+
+Vector3 GodotPhysicsDirectBodyState3D::get_constant_force() const {
+	return body->get_constant_force();
+}
+
+void GodotPhysicsDirectBodyState3D::set_constant_torque(const Vector3 &p_torque) {
+	if (!p_torque.is_equal_approx(Vector3())) {
+		body->wakeup();
+	}
+	body->set_constant_torque(p_torque);
+}
+
+Vector3 GodotPhysicsDirectBodyState3D::get_constant_torque() const {
+	return body->get_constant_torque();
 }
 
 void GodotPhysicsDirectBodyState3D::set_sleep_state(bool p_sleep) {

+ 14 - 3
servers/physics_3d/godot_body_direct_state_3d.h

@@ -64,13 +64,24 @@ public:
 
 	virtual Vector3 get_velocity_at_local_position(const Vector3 &p_position) const override;
 
-	virtual void add_central_force(const Vector3 &p_force) override;
-	virtual void add_force(const Vector3 &p_force, const Vector3 &p_position = Vector3()) override;
-	virtual void add_torque(const Vector3 &p_torque) override;
 	virtual void apply_central_impulse(const Vector3 &p_impulse) override;
 	virtual void apply_impulse(const Vector3 &p_impulse, const Vector3 &p_position = Vector3()) override;
 	virtual void apply_torque_impulse(const Vector3 &p_impulse) override;
 
+	virtual void apply_central_force(const Vector3 &p_force) override;
+	virtual void apply_force(const Vector3 &p_force, const Vector3 &p_position = Vector3()) override;
+	virtual void apply_torque(const Vector3 &p_torque) override;
+
+	virtual void add_constant_central_force(const Vector3 &p_force) override;
+	virtual void add_constant_force(const Vector3 &p_force, const Vector3 &p_position = Vector3()) override;
+	virtual void add_constant_torque(const Vector3 &p_torque) override;
+
+	virtual void set_constant_force(const Vector3 &p_force) override;
+	virtual Vector3 get_constant_force() const override;
+
+	virtual void set_constant_torque(const Vector3 &p_torque) override;
+	virtual Vector3 get_constant_torque() const override;
+
 	virtual void set_sleep_state(bool p_sleep) override;
 	virtual bool is_sleeping() const override;
 

+ 72 - 44
servers/physics_3d/godot_physics_server_3d.cpp

@@ -607,40 +607,40 @@ void GodotPhysicsServer3D::body_attach_object_instance_id(RID p_body, ObjectID p
 	}
 
 	ERR_FAIL_MSG("Invalid ID.");
-};
+}
 
 ObjectID GodotPhysicsServer3D::body_get_object_instance_id(RID p_body) const {
 	GodotBody3D *body = body_owner.get_or_null(p_body);
 	ERR_FAIL_COND_V(!body, ObjectID());
 
 	return body->get_instance_id();
-};
+}
 
 void GodotPhysicsServer3D::body_set_user_flags(RID p_body, uint32_t p_flags) {
 	GodotBody3D *body = body_owner.get_or_null(p_body);
 	ERR_FAIL_COND(!body);
-};
+}
 
 uint32_t GodotPhysicsServer3D::body_get_user_flags(RID p_body) const {
 	GodotBody3D *body = body_owner.get_or_null(p_body);
 	ERR_FAIL_COND_V(!body, 0);
 
 	return 0;
-};
+}
 
 void GodotPhysicsServer3D::body_set_param(RID p_body, BodyParameter p_param, const Variant &p_value) {
 	GodotBody3D *body = body_owner.get_or_null(p_body);
 	ERR_FAIL_COND(!body);
 
 	body->set_param(p_param, p_value);
-};
+}
 
 Variant GodotPhysicsServer3D::body_get_param(RID p_body, BodyParameter p_param) const {
 	GodotBody3D *body = body_owner.get_or_null(p_body);
 	ERR_FAIL_COND_V(!body, 0);
 
 	return body->get_param(p_param);
-};
+}
 
 void GodotPhysicsServer3D::body_reset_mass_properties(RID p_body) {
 	GodotBody3D *body = body_owner.get_or_null(p_body);
@@ -654,97 +654,125 @@ void GodotPhysicsServer3D::body_set_state(RID p_body, BodyState p_state, const V
 	ERR_FAIL_COND(!body);
 
 	body->set_state(p_state, p_variant);
-};
+}
 
 Variant GodotPhysicsServer3D::body_get_state(RID p_body, BodyState p_state) const {
 	GodotBody3D *body = body_owner.get_or_null(p_body);
 	ERR_FAIL_COND_V(!body, Variant());
 
 	return body->get_state(p_state);
-};
+}
 
-void GodotPhysicsServer3D::body_set_applied_force(RID p_body, const Vector3 &p_force) {
+void GodotPhysicsServer3D::body_apply_central_impulse(RID p_body, const Vector3 &p_impulse) {
 	GodotBody3D *body = body_owner.get_or_null(p_body);
 	ERR_FAIL_COND(!body);
 
-	body->set_applied_force(p_force);
+	_update_shapes();
+
+	body->apply_central_impulse(p_impulse);
 	body->wakeup();
-};
+}
 
-Vector3 GodotPhysicsServer3D::body_get_applied_force(RID p_body) const {
+void GodotPhysicsServer3D::body_apply_impulse(RID p_body, const Vector3 &p_impulse, const Vector3 &p_position) {
 	GodotBody3D *body = body_owner.get_or_null(p_body);
-	ERR_FAIL_COND_V(!body, Vector3());
-	return body->get_applied_force();
-};
+	ERR_FAIL_COND(!body);
+
+	_update_shapes();
 
-void GodotPhysicsServer3D::body_set_applied_torque(RID p_body, const Vector3 &p_torque) {
+	body->apply_impulse(p_impulse, p_position);
+	body->wakeup();
+}
+
+void GodotPhysicsServer3D::body_apply_torque_impulse(RID p_body, const Vector3 &p_impulse) {
 	GodotBody3D *body = body_owner.get_or_null(p_body);
 	ERR_FAIL_COND(!body);
 
-	body->set_applied_torque(p_torque);
+	_update_shapes();
+
+	body->apply_torque_impulse(p_impulse);
 	body->wakeup();
-};
+}
 
-Vector3 GodotPhysicsServer3D::body_get_applied_torque(RID p_body) const {
+void GodotPhysicsServer3D::body_apply_central_force(RID p_body, const Vector3 &p_force) {
 	GodotBody3D *body = body_owner.get_or_null(p_body);
-	ERR_FAIL_COND_V(!body, Vector3());
+	ERR_FAIL_COND(!body);
 
-	return body->get_applied_torque();
-};
+	body->apply_central_force(p_force);
+	body->wakeup();
+}
 
-void GodotPhysicsServer3D::body_add_central_force(RID p_body, const Vector3 &p_force) {
+void GodotPhysicsServer3D::body_apply_force(RID p_body, const Vector3 &p_force, const Vector3 &p_position) {
 	GodotBody3D *body = body_owner.get_or_null(p_body);
 	ERR_FAIL_COND(!body);
 
-	body->add_central_force(p_force);
+	body->apply_force(p_force, p_position);
 	body->wakeup();
 }
 
-void GodotPhysicsServer3D::body_add_force(RID p_body, const Vector3 &p_force, const Vector3 &p_position) {
+void GodotPhysicsServer3D::body_apply_torque(RID p_body, const Vector3 &p_torque) {
 	GodotBody3D *body = body_owner.get_or_null(p_body);
 	ERR_FAIL_COND(!body);
 
-	body->add_force(p_force, p_position);
+	body->apply_torque(p_torque);
 	body->wakeup();
-};
+}
 
-void GodotPhysicsServer3D::body_add_torque(RID p_body, const Vector3 &p_torque) {
+void GodotPhysicsServer3D::body_add_constant_central_force(RID p_body, const Vector3 &p_force) {
 	GodotBody3D *body = body_owner.get_or_null(p_body);
 	ERR_FAIL_COND(!body);
 
-	body->add_torque(p_torque);
+	body->add_constant_central_force(p_force);
 	body->wakeup();
-};
+}
 
-void GodotPhysicsServer3D::body_apply_central_impulse(RID p_body, const Vector3 &p_impulse) {
+void GodotPhysicsServer3D::body_add_constant_force(RID p_body, const Vector3 &p_force, const Vector3 &p_position) {
 	GodotBody3D *body = body_owner.get_or_null(p_body);
 	ERR_FAIL_COND(!body);
 
-	_update_shapes();
+	body->add_constant_force(p_force, p_position);
+	body->wakeup();
+}
 
-	body->apply_central_impulse(p_impulse);
+void GodotPhysicsServer3D::body_add_constant_torque(RID p_body, const Vector3 &p_torque) {
+	GodotBody3D *body = body_owner.get_or_null(p_body);
+	ERR_FAIL_COND(!body);
+
+	body->add_constant_torque(p_torque);
 	body->wakeup();
 }
 
-void GodotPhysicsServer3D::body_apply_impulse(RID p_body, const Vector3 &p_impulse, const Vector3 &p_position) {
+void GodotPhysicsServer3D::body_set_constant_force(RID p_body, const Vector3 &p_force) {
 	GodotBody3D *body = body_owner.get_or_null(p_body);
 	ERR_FAIL_COND(!body);
 
-	_update_shapes();
+	body->set_constant_force(p_force);
+	if (!p_force.is_equal_approx(Vector3())) {
+		body->wakeup();
+	}
+}
 
-	body->apply_impulse(p_impulse, p_position);
-	body->wakeup();
-};
+Vector3 GodotPhysicsServer3D::body_get_constant_force(RID p_body) const {
+	GodotBody3D *body = body_owner.get_or_null(p_body);
+	ERR_FAIL_COND_V(!body, Vector3());
+	return body->get_constant_force();
+}
 
-void GodotPhysicsServer3D::body_apply_torque_impulse(RID p_body, const Vector3 &p_impulse) {
+void GodotPhysicsServer3D::body_set_constant_torque(RID p_body, const Vector3 &p_torque) {
 	GodotBody3D *body = body_owner.get_or_null(p_body);
 	ERR_FAIL_COND(!body);
 
-	_update_shapes();
+	body->set_constant_torque(p_torque);
+	if (!p_torque.is_equal_approx(Vector3())) {
+		body->wakeup();
+	}
+}
 
-	body->apply_torque_impulse(p_impulse);
-	body->wakeup();
-};
+Vector3 GodotPhysicsServer3D::body_get_constant_torque(RID p_body) const {
+	GodotBody3D *body = body_owner.get_or_null(p_body);
+	ERR_FAIL_COND_V(!body, Vector3());
+
+	return body->get_constant_torque();
+}
 
 void GodotPhysicsServer3D::body_set_axis_velocity(RID p_body, const Vector3 &p_axis_velocity) {
 	GodotBody3D *body = body_owner.get_or_null(p_body);
@@ -758,7 +786,7 @@ void GodotPhysicsServer3D::body_set_axis_velocity(RID p_body, const Vector3 &p_a
 	v += p_axis_velocity;
 	body->set_linear_velocity(v);
 	body->wakeup();
-};
+}
 
 void GodotPhysicsServer3D::body_set_axis_lock(RID p_body, BodyAxis p_axis, bool p_lock) {
 	GodotBody3D *body = body_owner.get_or_null(p_body);

+ 15 - 10
servers/physics_3d/godot_physics_server_3d.h

@@ -203,19 +203,24 @@ public:
 	virtual void body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) override;
 	virtual Variant body_get_state(RID p_body, BodyState p_state) const override;
 
-	virtual void body_set_applied_force(RID p_body, const Vector3 &p_force) override;
-	virtual Vector3 body_get_applied_force(RID p_body) const override;
-
-	virtual void body_set_applied_torque(RID p_body, const Vector3 &p_torque) override;
-	virtual Vector3 body_get_applied_torque(RID p_body) const override;
-
-	virtual void body_add_central_force(RID p_body, const Vector3 &p_force) override;
-	virtual void body_add_force(RID p_body, const Vector3 &p_force, const Vector3 &p_position = Vector3()) override;
-	virtual void body_add_torque(RID p_body, const Vector3 &p_torque) override;
-
 	virtual void body_apply_central_impulse(RID p_body, const Vector3 &p_impulse) override;
 	virtual void body_apply_impulse(RID p_body, const Vector3 &p_impulse, const Vector3 &p_position = Vector3()) override;
 	virtual void body_apply_torque_impulse(RID p_body, const Vector3 &p_impulse) override;
+
+	virtual void body_apply_central_force(RID p_body, const Vector3 &p_force) override;
+	virtual void body_apply_force(RID p_body, const Vector3 &p_force, const Vector3 &p_position = Vector3()) override;
+	virtual void body_apply_torque(RID p_body, const Vector3 &p_torque) override;
+
+	virtual void body_add_constant_central_force(RID p_body, const Vector3 &p_force) override;
+	virtual void body_add_constant_force(RID p_body, const Vector3 &p_force, const Vector3 &p_position = Vector3()) override;
+	virtual void body_add_constant_torque(RID p_body, const Vector3 &p_torque) override;
+
+	virtual void body_set_constant_force(RID p_body, const Vector3 &p_force) override;
+	virtual Vector3 body_get_constant_force(RID p_body) const override;
+
+	virtual void body_set_constant_torque(RID p_body, const Vector3 &p_torque) override;
+	virtual Vector3 body_get_constant_torque(RID p_body) const override;
+
 	virtual void body_set_axis_velocity(RID p_body, const Vector3 &p_axis_velocity) override;
 
 	virtual void body_set_axis_lock(RID p_body, BodyAxis p_axis, bool p_lock) override;

+ 29 - 6
servers/physics_server_2d.cpp

@@ -93,13 +93,24 @@ void PhysicsDirectBodyState2D::_bind_methods() {
 
 	ClassDB::bind_method(D_METHOD("get_velocity_at_local_position", "local_position"), &PhysicsDirectBodyState2D::get_velocity_at_local_position);
 
-	ClassDB::bind_method(D_METHOD("add_central_force", "force"), &PhysicsDirectBodyState2D::add_central_force);
-	ClassDB::bind_method(D_METHOD("add_force", "force", "position"), &PhysicsDirectBodyState2D::add_force, Vector2());
-	ClassDB::bind_method(D_METHOD("add_torque", "torque"), &PhysicsDirectBodyState2D::add_torque);
 	ClassDB::bind_method(D_METHOD("apply_central_impulse", "impulse"), &PhysicsDirectBodyState2D::apply_central_impulse);
 	ClassDB::bind_method(D_METHOD("apply_torque_impulse", "impulse"), &PhysicsDirectBodyState2D::apply_torque_impulse);
 	ClassDB::bind_method(D_METHOD("apply_impulse", "impulse", "position"), &PhysicsDirectBodyState2D::apply_impulse, Vector2());
 
+	ClassDB::bind_method(D_METHOD("apply_central_force", "force"), &PhysicsDirectBodyState2D::apply_central_force, Vector2());
+	ClassDB::bind_method(D_METHOD("apply_force", "force", "position"), &PhysicsDirectBodyState2D::apply_force, Vector2());
+	ClassDB::bind_method(D_METHOD("apply_torque", "torque"), &PhysicsDirectBodyState2D::apply_torque);
+
+	ClassDB::bind_method(D_METHOD("add_constant_central_force", "force"), &PhysicsDirectBodyState2D::add_constant_central_force, Vector2());
+	ClassDB::bind_method(D_METHOD("add_constant_force", "force", "position"), &PhysicsDirectBodyState2D::add_constant_force, Vector2());
+	ClassDB::bind_method(D_METHOD("add_constant_torque", "torque"), &PhysicsDirectBodyState2D::add_constant_torque);
+
+	ClassDB::bind_method(D_METHOD("set_constant_force", "force"), &PhysicsDirectBodyState2D::set_constant_force);
+	ClassDB::bind_method(D_METHOD("get_constant_force"), &PhysicsDirectBodyState2D::get_constant_force);
+
+	ClassDB::bind_method(D_METHOD("set_constant_torque", "torque"), &PhysicsDirectBodyState2D::set_constant_torque);
+	ClassDB::bind_method(D_METHOD("get_constant_torque"), &PhysicsDirectBodyState2D::get_constant_torque);
+
 	ClassDB::bind_method(D_METHOD("set_sleep_state", "enabled"), &PhysicsDirectBodyState2D::set_sleep_state);
 	ClassDB::bind_method(D_METHOD("is_sleeping"), &PhysicsDirectBodyState2D::is_sleeping);
 
@@ -688,9 +699,21 @@ void PhysicsServer2D::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("body_apply_central_impulse", "body", "impulse"), &PhysicsServer2D::body_apply_central_impulse);
 	ClassDB::bind_method(D_METHOD("body_apply_torque_impulse", "body", "impulse"), &PhysicsServer2D::body_apply_torque_impulse);
 	ClassDB::bind_method(D_METHOD("body_apply_impulse", "body", "impulse", "position"), &PhysicsServer2D::body_apply_impulse, Vector2());
-	ClassDB::bind_method(D_METHOD("body_add_central_force", "body", "force"), &PhysicsServer2D::body_add_central_force);
-	ClassDB::bind_method(D_METHOD("body_add_force", "body", "force", "position"), &PhysicsServer2D::body_add_force, Vector2());
-	ClassDB::bind_method(D_METHOD("body_add_torque", "body", "torque"), &PhysicsServer2D::body_add_torque);
+
+	ClassDB::bind_method(D_METHOD("body_apply_central_force", "body", "force"), &PhysicsServer2D::body_apply_central_force);
+	ClassDB::bind_method(D_METHOD("body_apply_force", "body", "force", "position"), &PhysicsServer2D::body_apply_force, Vector2());
+	ClassDB::bind_method(D_METHOD("body_apply_torque", "body", "torque"), &PhysicsServer2D::body_apply_torque);
+
+	ClassDB::bind_method(D_METHOD("body_add_constant_central_force", "body", "force"), &PhysicsServer2D::body_add_constant_central_force);
+	ClassDB::bind_method(D_METHOD("body_add_constant_force", "body", "force", "position"), &PhysicsServer2D::body_add_constant_force, Vector2());
+	ClassDB::bind_method(D_METHOD("body_add_constant_torque", "body", "torque"), &PhysicsServer2D::body_add_constant_torque);
+
+	ClassDB::bind_method(D_METHOD("body_set_constant_force", "body", "force"), &PhysicsServer2D::body_set_constant_force);
+	ClassDB::bind_method(D_METHOD("body_get_constant_force", "body"), &PhysicsServer2D::body_get_constant_force);
+
+	ClassDB::bind_method(D_METHOD("body_set_constant_torque", "body", "torque"), &PhysicsServer2D::body_set_constant_torque);
+	ClassDB::bind_method(D_METHOD("body_get_constant_torque", "body"), &PhysicsServer2D::body_get_constant_torque);
+
 	ClassDB::bind_method(D_METHOD("body_set_axis_velocity", "body", "axis_velocity"), &PhysicsServer2D::body_set_axis_velocity);
 
 	ClassDB::bind_method(D_METHOD("body_add_collision_exception", "body", "excepted_body"), &PhysicsServer2D::body_add_collision_exception);

+ 29 - 14
servers/physics_server_2d.h

@@ -64,13 +64,24 @@ public:
 
 	virtual Vector2 get_velocity_at_local_position(const Vector2 &p_position) const = 0;
 
-	virtual void add_central_force(const Vector2 &p_force) = 0;
-	virtual void add_force(const Vector2 &p_force, const Vector2 &p_position = Vector2()) = 0;
-	virtual void add_torque(real_t p_torque) = 0;
 	virtual void apply_central_impulse(const Vector2 &p_impulse) = 0;
 	virtual void apply_torque_impulse(real_t p_torque) = 0;
 	virtual void apply_impulse(const Vector2 &p_impulse, const Vector2 &p_position = Vector2()) = 0;
 
+	virtual void apply_central_force(const Vector2 &p_force) = 0;
+	virtual void apply_force(const Vector2 &p_force, const Vector2 &p_position = Vector2()) = 0;
+	virtual void apply_torque(real_t p_torque) = 0;
+
+	virtual void add_constant_central_force(const Vector2 &p_force) = 0;
+	virtual void add_constant_force(const Vector2 &p_force, const Vector2 &p_position = Vector2()) = 0;
+	virtual void add_constant_torque(real_t p_torque) = 0;
+
+	virtual void set_constant_force(const Vector2 &p_force) = 0;
+	virtual Vector2 get_constant_force() const = 0;
+
+	virtual void set_constant_torque(real_t p_torque) = 0;
+	virtual real_t get_constant_torque() const = 0;
+
 	virtual void set_sleep_state(bool p_enable) = 0;
 	virtual bool is_sleeping() const = 0;
 
@@ -419,20 +430,24 @@ public:
 	virtual void body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) = 0;
 	virtual Variant body_get_state(RID p_body, BodyState p_state) const = 0;
 
-	//do something about it
-	virtual void body_set_applied_force(RID p_body, const Vector2 &p_force) = 0;
-	virtual Vector2 body_get_applied_force(RID p_body) const = 0;
-
-	virtual void body_set_applied_torque(RID p_body, real_t p_torque) = 0;
-	virtual real_t body_get_applied_torque(RID p_body) const = 0;
-
-	virtual void body_add_central_force(RID p_body, const Vector2 &p_force) = 0;
-	virtual void body_add_force(RID p_body, const Vector2 &p_force, const Vector2 &p_position = Vector2()) = 0;
-	virtual void body_add_torque(RID p_body, real_t p_torque) = 0;
-
 	virtual void body_apply_central_impulse(RID p_body, const Vector2 &p_impulse) = 0;
 	virtual void body_apply_torque_impulse(RID p_body, real_t p_torque) = 0;
 	virtual void body_apply_impulse(RID p_body, const Vector2 &p_impulse, const Vector2 &p_position = Vector2()) = 0;
+
+	virtual void body_apply_central_force(RID p_body, const Vector2 &p_force) = 0;
+	virtual void body_apply_force(RID p_body, const Vector2 &p_force, const Vector2 &p_position = Vector2()) = 0;
+	virtual void body_apply_torque(RID p_body, real_t p_torque) = 0;
+
+	virtual void body_add_constant_central_force(RID p_body, const Vector2 &p_force) = 0;
+	virtual void body_add_constant_force(RID p_body, const Vector2 &p_force, const Vector2 &p_position = Vector2()) = 0;
+	virtual void body_add_constant_torque(RID p_body, real_t p_torque) = 0;
+
+	virtual void body_set_constant_force(RID p_body, const Vector2 &p_force) = 0;
+	virtual Vector2 body_get_constant_force(RID p_body) const = 0;
+
+	virtual void body_set_constant_torque(RID p_body, real_t p_torque) = 0;
+	virtual real_t body_get_constant_torque(RID p_body) const = 0;
+
 	virtual void body_set_axis_velocity(RID p_body, const Vector2 &p_axis_velocity) = 0;
 
 	//fix

+ 15 - 9
servers/physics_server_2d_wrap_mt.h

@@ -213,18 +213,24 @@ public:
 	FUNC3(body_set_state, RID, BodyState, const Variant &);
 	FUNC2RC(Variant, body_get_state, RID, BodyState);
 
-	FUNC2(body_set_applied_force, RID, const Vector2 &);
-	FUNC1RC(Vector2, body_get_applied_force, RID);
-
-	FUNC2(body_set_applied_torque, RID, real_t);
-	FUNC1RC(real_t, body_get_applied_torque, RID);
-
-	FUNC2(body_add_central_force, RID, const Vector2 &);
-	FUNC3(body_add_force, RID, const Vector2 &, const Vector2 &);
-	FUNC2(body_add_torque, RID, real_t);
 	FUNC2(body_apply_central_impulse, RID, const Vector2 &);
 	FUNC2(body_apply_torque_impulse, RID, real_t);
 	FUNC3(body_apply_impulse, RID, const Vector2 &, const Vector2 &);
+
+	FUNC2(body_apply_central_force, RID, const Vector2 &);
+	FUNC3(body_apply_force, RID, const Vector2 &, const Vector2 &);
+	FUNC2(body_apply_torque, RID, real_t);
+
+	FUNC2(body_add_constant_central_force, RID, const Vector2 &);
+	FUNC3(body_add_constant_force, RID, const Vector2 &, const Vector2 &);
+	FUNC2(body_add_constant_torque, RID, real_t);
+
+	FUNC2(body_set_constant_force, RID, const Vector2 &);
+	FUNC1RC(Vector2, body_get_constant_force, RID);
+
+	FUNC2(body_set_constant_torque, RID, real_t);
+	FUNC1RC(real_t, body_get_constant_torque, RID);
+
 	FUNC2(body_set_axis_velocity, RID, const Vector2 &);
 
 	FUNC2(body_add_collision_exception, RID, RID);

+ 29 - 7
servers/physics_server_3d.cpp

@@ -94,13 +94,24 @@ void PhysicsDirectBodyState3D::_bind_methods() {
 
 	ClassDB::bind_method(D_METHOD("get_velocity_at_local_position", "local_position"), &PhysicsDirectBodyState3D::get_velocity_at_local_position);
 
-	ClassDB::bind_method(D_METHOD("add_central_force", "force"), &PhysicsDirectBodyState3D::add_central_force, Vector3());
-	ClassDB::bind_method(D_METHOD("add_force", "force", "position"), &PhysicsDirectBodyState3D::add_force, Vector3());
-	ClassDB::bind_method(D_METHOD("add_torque", "torque"), &PhysicsDirectBodyState3D::add_torque);
 	ClassDB::bind_method(D_METHOD("apply_central_impulse", "impulse"), &PhysicsDirectBodyState3D::apply_central_impulse, Vector3());
 	ClassDB::bind_method(D_METHOD("apply_impulse", "impulse", "position"), &PhysicsDirectBodyState3D::apply_impulse, Vector3());
 	ClassDB::bind_method(D_METHOD("apply_torque_impulse", "impulse"), &PhysicsDirectBodyState3D::apply_torque_impulse);
 
+	ClassDB::bind_method(D_METHOD("apply_central_force", "force"), &PhysicsDirectBodyState3D::apply_central_force, Vector3());
+	ClassDB::bind_method(D_METHOD("apply_force", "force", "position"), &PhysicsDirectBodyState3D::apply_force, Vector3());
+	ClassDB::bind_method(D_METHOD("apply_torque", "torque"), &PhysicsDirectBodyState3D::apply_torque);
+
+	ClassDB::bind_method(D_METHOD("add_constant_central_force", "force"), &PhysicsDirectBodyState3D::add_constant_central_force, Vector3());
+	ClassDB::bind_method(D_METHOD("add_constant_force", "force", "position"), &PhysicsDirectBodyState3D::add_constant_force, Vector3());
+	ClassDB::bind_method(D_METHOD("add_constant_torque", "torque"), &PhysicsDirectBodyState3D::add_constant_torque);
+
+	ClassDB::bind_method(D_METHOD("set_constant_force", "force"), &PhysicsDirectBodyState3D::set_constant_force);
+	ClassDB::bind_method(D_METHOD("get_constant_force"), &PhysicsDirectBodyState3D::get_constant_force);
+
+	ClassDB::bind_method(D_METHOD("set_constant_torque", "torque"), &PhysicsDirectBodyState3D::set_constant_torque);
+	ClassDB::bind_method(D_METHOD("get_constant_torque"), &PhysicsDirectBodyState3D::get_constant_torque);
+
 	ClassDB::bind_method(D_METHOD("set_sleep_state", "enabled"), &PhysicsDirectBodyState3D::set_sleep_state);
 	ClassDB::bind_method(D_METHOD("is_sleeping"), &PhysicsDirectBodyState3D::is_sleeping);
 
@@ -731,13 +742,24 @@ void PhysicsServer3D::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("body_set_state", "body", "state", "value"), &PhysicsServer3D::body_set_state);
 	ClassDB::bind_method(D_METHOD("body_get_state", "body", "state"), &PhysicsServer3D::body_get_state);
 
-	ClassDB::bind_method(D_METHOD("body_add_central_force", "body", "force"), &PhysicsServer3D::body_add_central_force);
-	ClassDB::bind_method(D_METHOD("body_add_force", "body", "force", "position"), &PhysicsServer3D::body_add_force, Vector3());
-	ClassDB::bind_method(D_METHOD("body_add_torque", "body", "torque"), &PhysicsServer3D::body_add_torque);
-
 	ClassDB::bind_method(D_METHOD("body_apply_central_impulse", "body", "impulse"), &PhysicsServer3D::body_apply_central_impulse);
 	ClassDB::bind_method(D_METHOD("body_apply_impulse", "body", "impulse", "position"), &PhysicsServer3D::body_apply_impulse, Vector3());
 	ClassDB::bind_method(D_METHOD("body_apply_torque_impulse", "body", "impulse"), &PhysicsServer3D::body_apply_torque_impulse);
+
+	ClassDB::bind_method(D_METHOD("body_apply_central_force", "body", "force"), &PhysicsServer3D::body_apply_central_force);
+	ClassDB::bind_method(D_METHOD("body_apply_force", "body", "force", "position"), &PhysicsServer3D::body_apply_force, Vector3());
+	ClassDB::bind_method(D_METHOD("body_apply_torque", "body", "torque"), &PhysicsServer3D::body_apply_torque);
+
+	ClassDB::bind_method(D_METHOD("body_add_constant_central_force", "body", "force"), &PhysicsServer3D::body_add_constant_central_force);
+	ClassDB::bind_method(D_METHOD("body_add_constant_force", "body", "force", "position"), &PhysicsServer3D::body_add_constant_force, Vector3());
+	ClassDB::bind_method(D_METHOD("body_add_constant_torque", "body", "torque"), &PhysicsServer3D::body_add_constant_torque);
+
+	ClassDB::bind_method(D_METHOD("body_set_constant_force", "body", "force"), &PhysicsServer3D::body_set_constant_force);
+	ClassDB::bind_method(D_METHOD("body_get_constant_force", "body"), &PhysicsServer3D::body_get_constant_force);
+
+	ClassDB::bind_method(D_METHOD("body_set_constant_torque", "body", "torque"), &PhysicsServer3D::body_set_constant_torque);
+	ClassDB::bind_method(D_METHOD("body_get_constant_torque", "body"), &PhysicsServer3D::body_get_constant_torque);
+
 	ClassDB::bind_method(D_METHOD("body_set_axis_velocity", "body", "axis_velocity"), &PhysicsServer3D::body_set_axis_velocity);
 
 	ClassDB::bind_method(D_METHOD("body_set_axis_lock", "body", "axis", "lock"), &PhysicsServer3D::body_set_axis_lock);

+ 29 - 14
servers/physics_server_3d.h

@@ -65,13 +65,24 @@ public:
 
 	virtual Vector3 get_velocity_at_local_position(const Vector3 &p_position) const = 0;
 
-	virtual void add_central_force(const Vector3 &p_force) = 0;
-	virtual void add_force(const Vector3 &p_force, const Vector3 &p_position = Vector3()) = 0;
-	virtual void add_torque(const Vector3 &p_torque) = 0;
 	virtual void apply_central_impulse(const Vector3 &p_impulse) = 0;
 	virtual void apply_impulse(const Vector3 &p_impulse, const Vector3 &p_position = Vector3()) = 0;
 	virtual void apply_torque_impulse(const Vector3 &p_impulse) = 0;
 
+	virtual void apply_central_force(const Vector3 &p_force) = 0;
+	virtual void apply_force(const Vector3 &p_force, const Vector3 &p_position = Vector3()) = 0;
+	virtual void apply_torque(const Vector3 &p_torque) = 0;
+
+	virtual void add_constant_central_force(const Vector3 &p_force) = 0;
+	virtual void add_constant_force(const Vector3 &p_force, const Vector3 &p_position = Vector3()) = 0;
+	virtual void add_constant_torque(const Vector3 &p_torque) = 0;
+
+	virtual void set_constant_force(const Vector3 &p_force) = 0;
+	virtual Vector3 get_constant_force() const = 0;
+
+	virtual void set_constant_torque(const Vector3 &p_torque) = 0;
+	virtual Vector3 get_constant_torque() const = 0;
+
 	virtual void set_sleep_state(bool p_sleep) = 0;
 	virtual bool is_sleeping() const = 0;
 
@@ -434,20 +445,24 @@ public:
 	virtual void body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) = 0;
 	virtual Variant body_get_state(RID p_body, BodyState p_state) const = 0;
 
-	//do something about it
-	virtual void body_set_applied_force(RID p_body, const Vector3 &p_force) = 0;
-	virtual Vector3 body_get_applied_force(RID p_body) const = 0;
-
-	virtual void body_set_applied_torque(RID p_body, const Vector3 &p_torque) = 0;
-	virtual Vector3 body_get_applied_torque(RID p_body) const = 0;
-
-	virtual void body_add_central_force(RID p_body, const Vector3 &p_force) = 0;
-	virtual void body_add_force(RID p_body, const Vector3 &p_force, const Vector3 &p_position = Vector3()) = 0;
-	virtual void body_add_torque(RID p_body, const Vector3 &p_torque) = 0;
-
 	virtual void body_apply_central_impulse(RID p_body, const Vector3 &p_impulse) = 0;
 	virtual void body_apply_impulse(RID p_body, const Vector3 &p_impulse, const Vector3 &p_position = Vector3()) = 0;
 	virtual void body_apply_torque_impulse(RID p_body, const Vector3 &p_impulse) = 0;
+
+	virtual void body_apply_central_force(RID p_body, const Vector3 &p_force) = 0;
+	virtual void body_apply_force(RID p_body, const Vector3 &p_force, const Vector3 &p_position = Vector3()) = 0;
+	virtual void body_apply_torque(RID p_body, const Vector3 &p_torque) = 0;
+
+	virtual void body_add_constant_central_force(RID p_body, const Vector3 &p_force) = 0;
+	virtual void body_add_constant_force(RID p_body, const Vector3 &p_force, const Vector3 &p_position = Vector3()) = 0;
+	virtual void body_add_constant_torque(RID p_body, const Vector3 &p_torque) = 0;
+
+	virtual void body_set_constant_force(RID p_body, const Vector3 &p_force) = 0;
+	virtual Vector3 body_get_constant_force(RID p_body) const = 0;
+
+	virtual void body_set_constant_torque(RID p_body, const Vector3 &p_torque) = 0;
+	virtual Vector3 body_get_constant_torque(RID p_body) const = 0;
+
 	virtual void body_set_axis_velocity(RID p_body, const Vector3 &p_axis_velocity) = 0;
 
 	enum BodyAxis {

+ 15 - 9
servers/physics_server_3d_wrap_mt.h

@@ -213,18 +213,24 @@ public:
 	FUNC3(body_set_state, RID, BodyState, const Variant &);
 	FUNC2RC(Variant, body_get_state, RID, BodyState);
 
-	FUNC2(body_set_applied_force, RID, const Vector3 &);
-	FUNC1RC(Vector3, body_get_applied_force, RID);
-
-	FUNC2(body_set_applied_torque, RID, const Vector3 &);
-	FUNC1RC(Vector3, body_get_applied_torque, RID);
-
-	FUNC2(body_add_central_force, RID, const Vector3 &);
-	FUNC3(body_add_force, RID, const Vector3 &, const Vector3 &);
-	FUNC2(body_add_torque, RID, const Vector3 &);
 	FUNC2(body_apply_torque_impulse, RID, const Vector3 &);
 	FUNC2(body_apply_central_impulse, RID, const Vector3 &);
 	FUNC3(body_apply_impulse, RID, const Vector3 &, const Vector3 &);
+
+	FUNC2(body_apply_central_force, RID, const Vector3 &);
+	FUNC3(body_apply_force, RID, const Vector3 &, const Vector3 &);
+	FUNC2(body_apply_torque, RID, const Vector3 &);
+
+	FUNC2(body_add_constant_central_force, RID, const Vector3 &);
+	FUNC3(body_add_constant_force, RID, const Vector3 &, const Vector3 &);
+	FUNC2(body_add_constant_torque, RID, const Vector3 &);
+
+	FUNC2(body_set_constant_force, RID, const Vector3 &);
+	FUNC1RC(Vector3, body_get_constant_force, RID);
+
+	FUNC2(body_set_constant_torque, RID, const Vector3 &);
+	FUNC1RC(Vector3, body_get_constant_torque, RID);
+
 	FUNC2(body_set_axis_velocity, RID, const Vector3 &);
 
 	FUNC3(body_set_axis_lock, RID, BodyAxis, bool);