void CalculateHover() { //Holds the normal of the ground Vector3 groundNormal; Ray ray = new Ray(transform.position, -transform.up); RaycastHit hitInfo; isOnGround = Physics.Raycast(ray, out hitInfo, groundDist, groundCheck); if (isOnGround) { //determine how high off the ground is float height = hitInfo.distance; //saves the normal of the ground groundNormal = hitInfo.normal.normalized; //use the PID settings to determine the required hover force float forcePercent = hoverPID.Seek(hoverHeight, height); //Calculates the total amount of hoverForce needed based on the grounds normal Vector3 force = groundNormal * hoverForce * forcePercent; //Calculate the force and direction of gravity. Vector3 gravity = -groundNormal * hoverForce * height; //Applies the hover and gravity forces rigidbody.AddForce(force, ForceMode.Acceleration); rigidbody.AddForce(gravity, ForceMode.Acceleration); } else { //If the player is not on the ground. Set normal to up. This prevents the player //from tipping over. groundNormal = Vector3.up; //Change the gravity applied to falling gravity. Vector3 gravity = -groundNormal * inAirGrav; rigidbody.AddForce(gravity, ForceMode.Acceleration); } //Calculate the pitch and roll of the player to match the orientetion of the ground. //This method uses projection. Vector3 projection = Vector3.ProjectOnPlane(transform.forward, groundNormal); Quaternion rotation = Quaternion.LookRotation(projection, groundNormal); //Move the ship to match the rotation of the ground. Uses lerp for smoothness. rigidbody.MoveRotation(Quaternion.Lerp(rigidbody.rotation, rotation, Time.deltaTime * 10f)); //Cosmetic rotation. Makes the player mesh to bank based on the rotation it is allready in. float angle = rollAngle * -input.rudder; Quaternion bodyRotation = transform.rotation * Quaternion.Euler(0f, 0f, angle); shipBody.rotation = Quaternion.Lerp(shipBody.rotation, bodyRotation, Time.deltaTime * 10f); }