0
\$\begingroup\$

I am working on a project where I want to create a 'scrolling' effect using the gyroscope on mobile devices. The basic idea is that I have an Image object in my scene and I want to be able to show different parts of it based on device rotation with the gyroscope. For example, you see the wall of a room, and by rotating your phone you can turn to see different parts of the room (but in 2D).

For now I managed to move my Image using Input.gyro.attitude.eulerAngles.x; from Gyroscope like this:

protected void Update()
{
    var x = transform.localPosition.x;
    var gyroX = Input.gyro.attitude.eulerAngles.x;
    x += -gyroX * Speed;

    BackgroundImage.transform.localPosition =
        new Vector3(x, transform.localPosition.y, transform.localPosition.z);

}

The problem I am seeing is that when Input.gyro.attitude.eulerAngles.x reaches 86.0 it starts decreasing. Even if you are rotating your phone to the right, it changes its direction.

I checked the documentation, examples over internet, but didn't find anything about that.

The only rotation axis which I am interested in is X, because the app will be in portrait mode and I want to be able to move the image only horizontally (by x).

So the phone's rotation has to be similar to what a user would do while taking a panoramic photo:

Example of device orientation

If you have any idea what can cause that issue and how can I fix it, or any other suggestions for how can I achieve the thing I want to create, please share your knowledge.

\$\endgroup\$
4
  • \$\begingroup\$ You probably don't want to use Euler angles for this. They're good for specifying one complete orientation to be used as-is. They're not good for decomposing that orientation into component parts (each component can change meaning depending on the values of the other components) or for dynamically modifying/comparing orientations. Can you phrase your desired control scheme in terms of direction vectors, perchance? These behave in a more uniform & intuitive manner. \$\endgroup\$
    – DMGregory
    Commented Oct 2, 2017 at 12:58
  • \$\begingroup\$ @DMGregory the idea which I am trying to achieve is that: 1. The main background image is centered and when I rotate my phone to left, the image should move according to the angle of rotation so the user can see the left part of the image. 2. If I rotate the phone to right, the idea is the same as above. Most of the stuff which I see over internet are for rotating the object, but since I am working on 2D, rotating the image is not an option, it has to move by X. \$\endgroup\$ Commented Oct 2, 2017 at 15:54
  • \$\begingroup\$ Try including a diagram in your question. Rotational movement plus different phone-holding orientations makes it easy for ambiguity to creep in. \$\endgroup\$
    – DMGregory
    Commented Oct 2, 2017 at 16:10
  • \$\begingroup\$ Just edited the question, with a little bit more info about the thing which I want to achieve. \$\endgroup\$ Commented Oct 2, 2017 at 16:33

2 Answers 2

1
\$\begingroup\$

rotationRateUnbiased will give you the change in rotation. Try summing the rotationRateUnbiased.x value by multiplying it by delta.time and speed. I had the same problem and solved like this:

float angle;
float speed = 100;

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


void Update()
{
    if (Input.gyro.enabled)
    {
        float gyroXin = Input.gyro.rotationRateUnbiased.y * Time.deltaTime * speed;
        angle -= gyroXin;

        // And do whatever you like with angle
    }
}
\$\endgroup\$
0
\$\begingroup\$

To pan your image based on the relative rotation of your phone, you'll want to use Gyroscope.rotationRateUnbiased instead of Gyroscope.attitude. The latter describes the current orientation of the phone, which means it will wrap around when you rotate your phone a full 360 degrees, and your magnitude depends on how far you are from Unity's global zero, not how fast you're turning your phone.

In contrast, rotationRateUnbiased gives the instantaneous speed of rotation about each axis, which sounds more like what you're looking for. Remember to scale the speed by deltaTime so your movement doesn't jump/stutter or show inconsistencies under framerate changes.

protected void Update()
{
    var x = transform.localPosition.x;

    // I'm assuming the x axis of the phone is the one crossing the phone's
    // long axis - the Unity docs are a bit coy about important details like this....
    var gyro = Input.gyro.rotationRateUnbiased.x * Time.deltaTime;

    x -= gyro * Speed;
    // You may want to clamp or wrap x here in your image space.

    BackgroundImage.transform.localPosition =
        new Vector3(x, transform.localPosition.y, transform.localPosition.z);
}
\$\endgroup\$
6
  • \$\begingroup\$ tried that, but the image is moving with a few pixels. checked the value which returns Input.gyro.rotationRateUnbiased.x, it's something like 0,0032242 / 0.0012323 ... I've used attitude, because it's the only object which gives me rotation angles as 0 / 360, but there is an issue as I described with decresing the value after reaching 86 degree. \$\endgroup\$ Commented Oct 3, 2017 at 12:54
  • \$\begingroup\$ So after var gyro = Input.gyro.rotationRateUnbiased.x * Time.deltaTime; x -= (gyro * Mathf.Rad2Deg) * Speed; (btw Speed = 5f) , still has almost the same result, with a little bit more movement. \$\endgroup\$ Commented Oct 3, 2017 at 13:05
  • \$\begingroup\$ Then make Speed much much much bigger. \$\endgroup\$
    – DMGregory
    Commented Oct 3, 2017 at 13:06
  • \$\begingroup\$ still lot more glitchy and not so accurate in my opinion..using Gyroscope.attitude was giving better results, but with the issue. \$\endgroup\$ Commented Oct 3, 2017 at 13:13
  • \$\begingroup\$ Then describe the glitches. We can't fix a problem without knowing what it is. \$\endgroup\$
    – DMGregory
    Commented Oct 3, 2017 at 13:28

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .