Setting linear/angular velocity having no effect in _integrate_forces callback

Godot Version



I’m making a physics-based game that takes place on a surface that’s tilted at an angle. On this surface are various rigid bodies that need to be constrained to this global tilted axis rather than locked to the default world axes. This functionality doesn’t seem to be available to a rigidbody in the inspector.

So, I’ve implemented a node which extends RigidBody3D with the _integrate_forces callback overridden to null out any linear or angular velocity in the set locked axes. Basically it transforms the state’s linear and angular velocity vectors into the node’s local basis, nulls out the appropriate vector components, and then transforms back to global coordinates and calls the set_linear and set_angular velocity methods on the state object.

Here’s my code:

extends RigidBody3D

class_name GlobalLockRigidBody

@export var lock_translation_x: bool = false
@export var lock_translation_y: bool = false
@export var lock_translation_z: bool = false
@export var lock_rotation_x: bool = false
@export var lock_rotation_y: bool = false
@export var lock_rotation_z: bool = false

func _integrate_forces(state):
	var local_linear_velocity = state.linear_velocity * global_basis.inverse()
	var local_angular_velocity = state.angular_velocity * global_basis.inverse()

	local_linear_velocity = Vector3(
		0 if lock_translation_x else local_linear_velocity.x,
		0 if lock_translation_y else local_linear_velocity.y,
		0 if lock_translation_z else local_linear_velocity.z

	local_angular_velocity = Vector3(
		0 if lock_rotation_x else local_angular_velocity.x,
		0 if lock_rotation_y else local_angular_velocity.y,
		0 if lock_rotation_z else local_angular_velocity.z

	state.set_linear_velocity(local_linear_velocity * global_basis)
	state.set_angular_velocity(local_angular_velocity * global_basis)

The issue I’m seeing is that those final set functions don’t seem to be having any effect. In the debugger I can see that the local linear and angular variables get reasonable values, and after nulling axes they are assigned to the state’s velocity, but when I run the scene another object hits this rigidbody and it starts spinning out of control in one of the axes that should be null.

I also tested simply setting the angular velocity to a constant value and had the same results. Seemingly no effect from the _integrate_forces method at all. Can anyone help me figure out what’s going on?