Yerdno
Yerdno

Reputation: 21

How to detect android phone rotation in Unity?

In my Unity app, I would like to detect, if an android phone with landscape orientation is tilted up or down - for example like here: https://lh3.ggpht.com/A-9UCSQn7nujEMF5qmJir2YKIHbu3ehFneELSXprBBId_TYhVONTCd3guPUgQ-qte6GO=h900-rw

Rotation vector sensor is probably the tool, which I am looking for, but I did not find how can I access it with Unity. I don't want it to be dependent on the speed, I just need to know, if the phone is facing a floor or a sky.

How can I detect the rotation?

Upvotes: 0

Views: 8937

Answers (3)

David
David

Reputation: 387

As @Demon mentioned you need to use Input.gyro.attitude but there are a few things you need to be mindful of:

#1 Make sure the device has a gyroscope:

if (!SystemInfo.supportsGyroscope)
{
    // Exit with message
}

#2 Make sure you enable the Gyroscope

Input.gyro.enabled = true;

#3 Convert from the gyroscopes right-hand coordinate system to Unity's left-hand coordinate system:

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

*** Edit ***

Here's the component to get the direction the phone is tilted:

using System;
using UnityEngine;
using UnityEngine.UI;

public class Orientation : MonoBehaviour
{
    public Text textComponent;
    public GameObject blockText;
    Gyroscope gyro;
    float initAng;

    const float angTolerance = 20;

    Quaternion gyroCalibration;
    void Start()
    {
        // Make sure device supprts Gyroscope
        if (!SystemInfo.supportsGyroscope) throw new Exception("Device does not support Gyroscopoe");

        gyro = Input.gyro;
        gyro.enabled = true;    // Must enable the gyroscope

        textComponent = GameObject.Find("Text").GetComponent<Text>();
        blockText = GameObject.Find("Block Text");

        Quaternion attitude = Attitude();
        initAng = Elevation(attitude);
    }

    // Update is called once per frame
    void Update()
    {

        Quaternion attitude = Attitude();
        float ang = Elevation(attitude) - initAng;

        String dirStr;
        if (ang < -angTolerance)
           dirStr = "Down";
        else if (ang > angTolerance)
            dirStr = "Up";
        else
            dirStr = "Center";

        textComponent.text = ang.ToString() + "\n" + dirStr;    // +ang = up   -ang = down
    }

    private Quaternion Attitude()
    {
        Quaternion rawAttitude = gyro.attitude;             // Get the phones attitude in phone space
        Quaternion attitude = GyroToUnity(rawAttitude);     // Convert phone space to Unity space

        return attitude;
    }

    private static Quaternion GyroToUnity(Quaternion q)
    {
        return Quaternion.Euler(90, 0, 0) * new Quaternion(q.x, q.y, -q.z, -q.w);
    }

    private static float Elevation(Quaternion attitude)
    {
        Vector3 dir = attitude * Vector3.forward;           // Convert Quaterinon to Dir
        Vector2 horizontalDir = new Vector2(dir.x, dir.z);
        float horizontalDis = horizontalDir.magnitude;
        float ang = Mathf.Atan2(dir.y, horizontalDis) * Mathf.Rad2Deg;  // Calculate the elevation

        return ang;
    }
}

You could just use 'deviceOrientation()' but there are two advantages to doing it this way:

#1 You have control over how far you need to tilt the phone for it to register a tilt were using deviceOrientation you have to tilt the phone very far before it registers a tilt

#2 It uses the device starting elevation as a reference which compensates for a user that either holds the phone slightly down or up in general

Upvotes: 1

Gal Lahat
Gal Lahat

Reputation: 60

One of the simplest ways to achieve that is with Input.deviceOrientation.

if (Input.deviceOrientation == DeviceOrientation.Portrait)

or

if (Input.deviceOrientation == DeviceOrientation.LandscapeLeft)

you can also check for: Unknown, Portrait, PortraitUpsideDown, LandscapeLeft, LandscapeRight, FaceUp and FaceDown.

Have a look at: https://docs.unity3d.com/ScriptReference/Input-deviceOrientation.html

Upvotes: 2

Demon
Demon

Reputation: 494

I believe you have to use Gyroscope.attitude

using UnityEngine;
using System.Collections;

public class ExampleClass : MonoBehaviour {
    void Update() {
        transform.rotation = Input.gyro.attitude;
    }
}

ref :https://docs.unity3d.com/ScriptReference/Gyroscope-attitude.html

Upvotes: 1

Related Questions