Hello all,
I’m trying to write code to rotate a character in a space environment, but no matter which implementation I choose I run into the same two problems. The playing field is the space between planets, and so I need the player to be able to rotate on X, Y, and Z axis. Here’s one attempt at that:
// Mouse movement (these are captured in an earlier function within Update)
inputLookX = Input.GetAxis(axisLookHorizontal); // Mouse X
inputLookY = Input.GetAxis(axisLookVertical); // Mouse Y
inputKeyRoll = Input.GetKey(keyRoll); // R
float accMouseX = 0f;
float accMouseY = 0f;
float verticalRotation = 0f;
float horizontalRotation = 0f;
float rollRotation = 0f;
float mouseSensitivity = 5f;
float mouseSnappiness = 20f;
playerTx = transform;
void ProcessLook()
{
accMouseX = Mathf.Lerp(accMouseX, inputLookX, mouseSnappiness * Time.deltaTime);
accMouseY = Mathf.Lerp(accMouseY, inputLookY, mouseSnappiness * Time.deltaTime);
float mouseX = accMouseX * mouseSensitivity * 100f * Time.deltaTime;
float mouseY = accMouseY * mouseSensitivity * 100f * Time.deltaTime;
// change rotations by mouse position
verticalRotation -= mouseY;
if (inputKeyRoll)
{
rollRotation -= mouseX;
}
else
{
horizontalRotation += mouseX;
}
// finally, rotate player
playerTx.localRotation = Quaternion.Euler(verticalRotation, horizontalRotation, rollRotation);
}
And while this works fine for X and Y, once I rotate on the Z axis the other rotations get funky. From what I’ve researched, this is the “correct” way to do movement with the mouse (storing the values and manually rotating), but I get some strange results.
For example, rotating 90 degrees on the Z axis, then attempting to rotate on the X axis causes a rotation on the world’s axis, not the player’s, so it looks like what a rotation on the Y axis should be from that orientation. Beyond that, when my character is upside down, rotating on the X axis is reversed, because I’m rotating on world space.
So the best solution I could find to that problem was to use Rotate(), like below:
void NewProcessLook()
{
float mouseX = inputLookX * mouseSensitivity * 100f * Time.deltaTime;
float mouseY = inputLookY * mouseSensitivity * 100f * Time.deltaTime;
// initialize target rotations
Vector3 targetRotation = Vector3.zero;
// switch rotational axis if holding 'R'
if (inputKeyRoll)
{
targetRotation.x = -mouseY;
targetRotation.z = -mouseX; // moving on z axis
}
else
{
targetRotation.y = mouseX;
targetRotation.x = -mouseY;
}
playerTx.Rotate(targetRotation, Space.Self);
}
This works perfectly and solves all the above issues. Except, it creates one more: when I move the mouse in a circle, it creates roll rotation. I know this is because rotating on X then Y moves you on the Z axis, and the only suggestion I’ve found is to store the rotations myself like the first solution, but then I’m back to square one.
Is there a better way to do this that I’m not aware of? I’d like to use some sort of local rotation to maintain the character’s roll, but when I’ve tried saving the current x, y, and z rotations I run into all the Quaternion math I’m not quite literate in yet.
One more method I’ve tried is to split the rotations between a quaternion and Rotate(), doing Y and Z through a quaternion and X through Rotate(), but that causes more problems that solves them.