1
votes

I have a game in landscape left mode. What I am trying to do is get the phone tilt on the x and y axis but a bunch of weird things happen. For example, turning the phone on the z axis affects the calculations of the x and z axis. Quaternions are a hard thing to wrap my head around, any help? The code is my closest solution.

public float rotationX;
public float rotationZ;
public float gyroscopeX, gyroscopeY, gyroscopeZ;
public Quaternion rotated;

private void Start ()
{
    Input.gyro.enabled = true;
}

private void FixedUpdate ()
{
    rotated = ConvertRotation(Input.gyro.attitude) * GetRotFix() * Quaternion.Euler(Vector3.forward * 90);
    rotated *= Quaternion.AngleAxis(-Input.gyro.attitude.z, Vector3.forward);
    rotationX = ClampAngle(rotated.x*90, -45, 45);
    rotationZ = ClampAngle(rotated.y*90, -45, 45);

    transform.rotation = Quaternion.Euler(-rotationZ, 0, rotationX);
}

private static Quaternion ConvertRotation(Quaternion q)
{
    return new Quaternion(q.x, q.y, -q.z, -q.w);
}

private Quaternion GetRotFix()
{
    if (Screen.orientation == ScreenOrientation.Portrait)
        return Quaternion.identity;
    if (Screen.orientation == ScreenOrientation.LandscapeLeft || Screen.orientation == ScreenOrientation.Landscape)
        return Quaternion.Euler(0, 0, -90);
    if (Screen.orientation == ScreenOrientation.LandscapeRight)
        return Quaternion.Euler(0, 0, 90);
    if (Screen.orientation == ScreenOrientation.PortraitUpsideDown)
        return Quaternion.Euler(0, 0, 180);
    return Quaternion.identity;
}

I would like the object to rotate only on its x and z axes according to phone's x and y axes independently. However, turning the phone on its z axis will cause the game object to rotate diagonally if the phone is tilting only on one axis.

1

1 Answers

0
votes

In the real world, physically, the phone has an orientation, which is a four dimensional vector: 3 dimensions to describe a forward direction (F), and a 4th dimension to describe how much the phone is rotated (R) about that forward direction.

However, due to hardware limitations and poor planning on the part of platform developers, phones only report Euler angles. That is not sufficient for determining an orientation. What this means is that for each possible screen orientation (i.e. ScreenOrientation.LandscapeLeft you observe, there are at least two (indeed infinitely many) Euler angles that are at least perpendicular (i.e. the rotation R is 90ยบ different) and at worst oriented in opposite directions (i.e. F and -F have the same screen orientation).

Use a well-reviewed asset store package instead, or study an open source solution like Parallax instead.

There is no correct answer for how to interpret a 3-dimensional gyroscope measurement as a 4-dimensional orientation, it is a qualitative decision based on your needs. However most games assume that players will be holding their device landscape with the forward direction parallel to the Earth, rotating about that forward (i.e. like driving a car), so that's what most documentation / tutorials online will describe and what you will find is most robust.