Making a Rigidbody return to being level

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

I am working on a game where mouse input affects the torque of the RigidBody but I would like the RigiBbody to return to being level if certain conditions are met.

Currently the angling working right but once you set the mouse in the deadzone and make the mouse_input equal to 0, then the RigidBody will teeter back and forth and not settle.

I would expect this act like so:

  • User angles the RigidBody to an angle to 45
  • User decides they are done and move the mouse to the deadzone, making the mouse_input 0.
  • The level function applies a mouse_input value of the opposite angle causing the RigidBody to level out.

I created a gif of the script below in action: Animated GIF - Find & Share on GIPHY

extends RigidBody
var window_half: Vector2 = OS.get_window_size() / 2
var deadzone: Rect2 = Rect2(Vector2(window_half.x - 200, window_half.y - 200), Vector2(400, 400))

# The input amount set by mouse motion.
var mouse_input: float = 0.0
# The angle of the box.
var box_angle: float = 0.0

# Nothing to do in ready, pass.
func _ready():
	pass

# Each frame we check the mouse position and apply the correct force to make the body
# go in the desired direction.
func _process(delta):
	get_mouse_position()
	calculate_angle()
	level()
	calculate_torque()

# Check to see if the mouse is in the deadzone and if not we set a value to the mouse_input.
func get_mouse_position():
	var mouse_pos = get_viewport().get_mouse_position()

	if deadzone.has_point(mouse_pos):
		mouse_input = 0.0
		return

	if mouse_pos.y > deadzone.position.y:
		mouse_input = 0.05
	elif mouse_pos.y < deadzone.position.y:
		mouse_input = -0.05

# Calculate the angle of the RigidBody.
func calculate_angle():
	var flat_forward = get_global_transform().basis.z
	flat_forward.z *= 1
	flat_forward.y = 0
	
	if flat_forward.length() > 0:
		flat_forward = flat_forward.normalized()
		var local_flat_forward = to_local(flat_forward)
		box_angle = atan2(local_flat_forward.y, local_flat_forward.z)

# If the mouse is not providing any input, we want to level out the RigidBody by applying
# an opposing force until it's equal.
func level():
	if mouse_input == 0.0:
		mouse_input = -box_angle

# Add the torque to make the RigidBody move.
func calculate_torque():
	var torque = Vector3.ZERO
	torque += mouse_input * get_global_transform().basis.x
	add_torque(torque)