I have a rigidbody with 4 wheel colliders attached. To get the rigidbody airborne I first add a force to the front of rigidbody then I add a force to the back of the rigidbody. This causes the it to become airborne.
Once the rigidbody has become airborne I want it to stop rotating and remain level to the surface normal below it.
The closest I have come to doing this is to do a raycast downward from the rigidbody to get the hit.normal then monitor the dot product between hit.normal and the rigidbody transform.up and once this value is close to 1 kill all angular velocity.
However since I’m using forces to make the rigidbody airborne the Z axis rotation value is sometimes not level to the ground thus causing the dot product to never be near 1. It normally happens once the board is airborne and it starts to “roll” which is not a desired effect.
I also thought freezing the Z and Y rotations would help stabilize it a bit but I still get some rotation along the Z axis.
I then tried to store the rotation of the rigidbody prior to becoming airborne and rotate it back to that rotation once airborne but I could not get it to rotate smoothly. And it failed in certain cases such as if it became airborne off the side of an incline (the z axis would start off rotated) and the surface it would land on is level.
Here is a little Visual representation of what Im describing as well as some code I currently have. Id appreciate any advise or suggestions. Thanks.
if(controller.OllieInput())
{
rigidbody.constraints = RigidbodyConstraints.FreezeRotationY | RigidbodyConstraints.FreezeRotationZ;
rigidbody.AddForceAtPosition(backForce,backForceLoc.transform.position);
Invoke ("addingForce",timeBetweeenSecondForce);
rigidbody.constraints = RigidbodyConstraints.None;
currentState = PlayerStates.Airborne;
}
void Airborne_FixedUpdate()
{
if(!isBoardLevel)
{
Debug.DrawRay(transform.position,-transform.up);
RaycastHit hit;
//sometimes doesnt level off since the z axis rotation is not near 0
//the force will cause the board to roll a bit
if(Physics.Raycast(transform.position, -transform.up, out hit))
{
float dot = Vector3.Dot(transform.up,hit.normal);
if(dot <= 1 dot >= 0.999)
{
Debug.Log ("board is level");
rigidbody.angularVelocity = Vector3.zero;
isBoardLevel = true;
}
}
}
}