Hi all, I’m currently scripting a player controller script for a plane. I have chosen simplistic controls in that if you press a or d, the plane banks up to 40° to either side (the angle is scaled by the plane’s speed up to the 40° maximum) and yaws to either side at the same time. Pitch is controlled separately by w and s at present.
I’m controlling everything via the plane’s rigidbody.MoveRotation using Quaternion.Euler rotations. The issue is the obvious Physics situation - if the plane banks to a side and then yaws, it’s going to pitch down slightly and cause it to move downwards. I want to basically cancel this out so that it (unrealistically) just yaws left and right without pitch difference.
The following is the current method for controlling the plane via the WASD keys:
// Detect if "w" key is pressed down
if (Input.GetKey("w") == true)
{
// Pitch the ship's rigidbody down and save its new pitch (X) angle
shipRigidbody.MoveRotation(shipRigidbody.rotation * Quaternion.Euler(shipPitchSpeed * Time.fixedDeltaTime, 0.0f, 0.0f));
shipPitchAngle = shipRigidbody.rotation.eulerAngles.x;
// Detect if ship has pitched down too far and if so, clip the pitch to the maximum pitch down angle
if ((shipRigidbody.rotation.eulerAngles.x > shipPitchDownMax && shipRigidbody.rotation.eulerAngles.x < (shipPitchDownMax + 5.0f)))
{
shipRigidbody.rotation = Quaternion.Euler(shipPitchDownMax, shipYawAngle, shipRigidbody.rotation.eulerAngles.z);
}
}
// Detect if "s" key is pressed down
if (Input.GetKey("s") == true)
{
// Pitch the ship's rigidbody up and save its new pitch (X) angle
shipRigidbody.MoveRotation(shipRigidbody.rotation * Quaternion.Euler(-(shipPitchSpeed * Time.fixedDeltaTime), 0.0f, 0.0f));
shipPitchAngle = shipRigidbody.rotation.eulerAngles.x;
// Detect if ship has pitched up too far and if so, clip the pitch to the maximum pitch up angle
if (shipRigidbody.rotation.eulerAngles.x > (shipPitchUpMax - 5.0f) && shipRigidbody.rotation.eulerAngles.x < shipPitchUpMax)
{
shipRigidbody.rotation = Quaternion.Euler(shipPitchUpMax, shipYawAngle, shipRigidbody.rotation.eulerAngles.z);
}
}
// Detect if "a" key is pressed down and if so, yaw and roll the ship's rigidbody left and set boolean such that the ship has to return from roll
if (Input.GetKey("a") == true)
{
// Yaw the ship left and save its new yaw angle
shipRigidbody.MoveRotation(shipRigidbody.rotation * Quaternion.Euler(0.0f, -(shipYawSpeed * Time.fixedDeltaTime) * shipYawAngleMultiplier, 0.0f));
shipYawAngle = shipRigidbody.rotation.eulerAngles.y;
// Smoothly roll the ship left, maintaining its yaw angle
shipRigidbody.rotation = Quaternion.Slerp(shipRigidbody.rotation, Quaternion.Euler(shipPitchAngle, shipYawAngle, shipRollAngle * shipRollAngleMultiplier), shipRollSpeed * Time.fixedDeltaTime);
shipReturnFromRoll = false;
}
// Detect if "a" key is released and if so, set boolean so ship returns from roll
else if (Input.GetKeyUp("a") == true)
{
shipReturnFromRoll = true;
}
// Detect if "d" key is pressed down and if so, yaw and roll the ship's rigidbody right and set boolean such that the ship has to return from roll
if (Input.GetKey("d") == true)
{
// Yaw the ship right and save its new yaw angle
shipRigidbody.MoveRotation(shipRigidbody.rotation * Quaternion.Euler(0.0f, (shipYawSpeed * Time.fixedDeltaTime) * shipYawAngleMultiplier, 0.0f));
shipYawAngle = shipRigidbody.rotation.eulerAngles.y;
// Smoothly roll the ship right, maintaining its yaw angle
shipRigidbody.rotation = Quaternion.Slerp(shipRigidbody.rotation, Quaternion.Euler(shipPitchAngle, shipYawAngle, -shipRollAngle * shipRollAngleMultiplier), shipRollSpeed * Time.fixedDeltaTime);
shipReturnFromRoll = false;
}
// Detect if "d" key is released and if so, set boolean so ship returns from roll
else if (Input.GetKeyUp("d") == true)
{
shipReturnFromRoll = true;
}
// If the boolean states that the ship has to return from roll, carry out the return from roll but to the same pitch and yaw angles
if (shipReturnFromRoll == true)
{
shipRigidbody.rotation = Quaternion.Slerp(shipRigidbody.rotation, Quaternion.Euler(shipPitchAngle, shipYawAngle, 0.0f), shipRollSpeed * Time.fixedDeltaTime);
}
// If the ship is close to having returned to its pre-roll orientation, set it to its pre-roll orientation and set the boolean that the ship has returned from roll
if (shipReturnFromRoll == true && (Quaternion.Angle(shipRigidbody.rotation, Quaternion.Euler(shipPitchAngle, shipYawAngle, 0.0f)) < 0.5f))
{
shipRigidbody.rotation = Quaternion.Euler(shipPitchAngle, shipYawAngle, 0.0f);
shipReturnFromRoll = false;
}
The variable shipRollAngleMultiplier is calculated as follows:
// Calculate the ship's current speed to maximum speed ratio (forced absolute magnitude)
shipCurrentSpeedToMaxRatio = Mathf.Abs(Vector3.Magnitude(shipRigidbody.velocity) / shipMaxSpeed);
The trouble I’m currently having is that if I simply try to cancel out the pitch angle, it cancels out the entire pitch angle (including the user input), not just the downward pitch due to banking. Thank you. I appreciate any help in advance.