How to avoid VehicleBody to overturn in midair?

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

Hi, I apologize in advance if I can’t express myself better than I do, since I’m not fluent in english.

I’m trying to make a Mario Kart-like game, so I want the vehicles to not overturn when they are in midair after jumping from a ramp. Right now, I’m using the VehicleBody node, and I tested a lot of things but I think I don’t have enough knowledge to achieve what I want.

I thought the expected behaviour should be that, if the angle between the car’s normal and a Vector3(0, 1, 0) pointing upwards is bigger than a certain value, the car should rotate in a way that it’s normal vector goes back to Vector3(0, 1, 0). And I can’t find the way to accomplish this. How can I get the rotation axis, so that the car rotates in the correct direction?

I’m happy if someone would tell me what steps should I take so I can translate it to code. (I guess I can do what I need using this VehicleBody node, right?)

:bust_in_silhouette: Reply From: ephemeration

Hi, I stumbled upon this question while trying to solve this, and wanted to share my solution. It’s still pretty basic, but got me started in the right direction. I’m not going all the way back to vertical, but instead just clamping at the tilt_limit, which I’ve set as PI/4.

Since we’re modifying the physics state directly, this should be done in _integrate_forces. The quaternion I create as the target upright could probably be done in a better way, but this does at least keep the car’s forward direction as close to the same as possible.

If you want to return to upright, you could consider applying an angular force in addition to or instead of this solution.

func _integrate_forces(state):
	var angle = abs(Vector3.UP.angle_to(state.transform.basis.y))
	if (angle > tilt_limit):
		var upright = Quat(Vector3.UP * state.transform.basis.get_euler().y)
		var weight = (angle - tilt_limit) / angle
		state.transform.basis = Basis(state.transform.basis.get_rotation_quat().slerp(upright, weight))