Control Camera Rotation with Mobile Device Gyroscope
I can't seem to get the Gyroscope to control the camera correctly in Android. I'm trying to build a game that uses a mobile device held horizontally as a view port into the game world. Where the top of the device would be pointing to the left and the bottom of the device would be pointing to the right. Then rotating the device will cause the camera to follow the rotation. I'm getting varied results depending on which real world direction I'm facing when I start the game. If I'm facing South the results are perfect, exactly what I want. However, if I'm facing North rotating Left rotates the camera Right, and rotating Right rotates the camera Left. As you can imagine everything in between is kind of meh.. Please see my code below and let me know if there is anything I can update to make the Camera follow the device rotation correctly regardless of what real world direction the user is facing. Also, some info on my setup. I've got a Player object which is stationary for the most part, but I have a script to rotate the player back to facing the +Z axis after considering the initial gyroscope rotation.
public class RotatePlayer : MonoBehaviour {
private float gyroTimeout = 0f;
private GyroCamera gyroCam;
// Use this for initialization
void Start () {
gyroCam = Camera.main.GetComponent<GyroCamera> ();
StartCoroutine ("GetTheYCalibration");
}
public void RotatePlayerYAxis()
{
float yAngle = gyroCam.GetYAngle ();
/* think of this as rotating the camera base */
this.transform.Rotate (new Vector3 (0f, 0f, yAngle));
}
IEnumerator GetTheYCalibration()
{
// provide some time for gyro initialization
while (gyroTimeout > -30) {
gyroTimeout -= Time.realtimeSinceStartup;
yield return null;
}
RotatePlayerYAxis ();
}
}
The camera is a child of the Player object and uses the below script to control the Camera's rotation.
public class GyroCamera : MonoBehaviour
{
private float initialYAngle = 0f;
private Gyroscope gyro;
private Quaternion gyroAttitude;
private bool gyroSupport;
private bool gyroEnabled;
// sensitivity vars
public float speed = 4.0f;
public float sensitivity = 0.8f;
void Start()
{
gyroSupport = SystemInfo.supportsGyroscope;
if (gyroSupport) {
gyro = Input.gyro;
gyroEnabled = true;
gyro.enabled = true;
} else {
gyroEnabled = false;
print ("NO GYRO");
}
ApplyCalibration ();
}
void Update()
{
if (gyroEnabled) {
ApplyGyroRotation ();
}
}
void ApplyGyroRotation()
{
Quaternion newRotation = Quaternion.Slerp(gyroAttitude,
Input.gyro.attitude,
Time.deltaTime * speed * sensitivity);
transform.localRotation = newRotation;
transform.Rotate( 30f, 0f, 180f, Space.Self ); // Swap "handedness" of quaternion from gyro.
transform.Rotate( 90f, 180f, 0f, Space.World ); // Rotate to make sense as a camera pointing out the back of your device.
// save the current gyro rotation for the next update
gyroAttitude = newRotation;
}
void ApplyCalibration()
{
transform.localRotation = Input.gyro.attitude;
transform.Rotate( 30f, 0f, 180f, Space.Self ); // Swap "handedness" of quaternion from gyro.
transform.Rotate( 90f, 180f, 0f, Space.World ); // Rotate to make sense as a camera pointing out the back of your device.
initialYAngle = transform.eulerAngles.y; // Save the angle around y axis in order to rotate the player accordingly
}
/* Used to get the original Y Angle in order to rotate the player
* in the positive Z direction regardless of which direction the user
* was facing when they started playing
*/
public float GetYAngle() {
ApplyCalibration ();
return initialYAngle;
}
}
Any assistance is greatly appreciated as I've been struggling to fix this issue for quite some time.
Thanks!
Answer by 76bigfoot · Apr 29, 2016 at 03:51 PM
Thanks Rotavele, I don't know if it had anything to do with the direction of rotation. Maybe. Your response did inspire me to test the RotatePlayerYAxis function with some different options. I noticed that the yAngle returned from the GyroCam was usually negative so I updated line 17 from the RotatePlayer class to :
this.transform.Rotate (new Vector3 (0f, 0f, 360f+yAngle));
I don't think this is a 100% solution as I did see the problem pop up once during testing, but it does seem to reduce the occurrence of the issue. I would think for Euler angles -X would be equal to 360-X, but maybe not.
Thanks!
Answer by Rotavele · Apr 13, 2016 at 05:42 AM
First I would just like to say I have no experience with the gyroscope, but from reading your question I was wondering if it just inverting the controls when facing north could fix it as a temporary band aid.
From reading your code (again I have no experience with the gyrocscope) I noticed there is only one rotation method instead of two (Clockwise and Counterclockwise). From your description: that may be the issue at hand. Just thought I would let you know. I hope you get your solution soon.
Your answer
Follow this Question
Related Questions
[8bitdo zero controller] Get D-PAD Events (Android) 3 Answers
Input.gyro seems not working on android 8.1 0 Answers
My VR controller wont work after i imported it into an android device 0 Answers
gyroscope enabled but not working on android device 6 Answers
Android gyro z-axis drift problem 0 Answers