Reputation: 21
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
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
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
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