- Home /
Help requested: Google VR / Phone rotation to gameobject.
Hi,
So I've been working on this project that requires accurate android gyroscope inputs. The goal is to the the camera to rotate around the world by rotating an empty game object. The rotation of this gameobject should mimic the phone's rotation.
I thought of just using Google VR and getting the values from there, but I can't disable the two-camera view easily. I've managed to figure out a way to disable it during runtime (it still shows two viewports during the unity splash screen, after which it switches to full screen), but that causes screen distortion that appears to be zoomed in. Making the phone sleep and then waking it back up seems to fix the screen distortion and it shows exactly what I want, but then the app crashes after 10 seconds.
GvrViewer.Instance.ToggleDeviceVRMode(false);
There must be a better way then half-assing it like I did. I can't find a setting anywhere to make google VR one single fullscreen image (setting VRMode Enables to false doesn't change anything), and there isn't a setting in the app itself.
Instead of Google VR I've also tried directly linking the gameobject rotation with the phone through input.acceleration, but that results in jitter.
//This happens in the Update function in the gameobject that I want to rotate.
transform.rotation = new Quaternion(Input.acceleration.x / 2, Input.acceleration.y / 2, Input.acceleration.z / 2, 0.0f);
transform.rotation = Quaternion.Lerp(transform.rotation, new Quaternion(Input.acceleration.x /2, Input.acceleration.y /2, Input.acceleration.z /2, 0.0f), 0.5f);
Up till now the best solution I've found is this:
//This function is called from the Update function.
void PlayGyro()
{
for (int i = 0; i < gyroSliders.Count; i++)
{
gyroValues[i] = gyroSliders[i].value;
gyroSliders[i].GetComponentInChildren<Text>().text = gyroSliders[i].value.ToString("00.00");
}
transform.Rotate(-Input.gyro.rotationRateUnbiased.x * gyroValues[0], -Input.gyro.rotationRateUnbiased.y * gyroValues[1], Input.gyro.rotationRateUnbiased.z * gyroValues[2]);
}
The above gives me a nice smooth rotation, but it doesn't match the phone's rotation. If I turn the phone 180° the object will be rotated 100° for example, hence the sliders to fine tune it. However this would mean having to manually recalibrate the sliders every time you want to play the game with accurate movement.
So I'm asking: Is there anyone with experience with these problems? I've been googling for the past two days and would appreciate suggestions, either for:
making Google VR start with one fullscreen view without distortion,
or accurately getting the phone's rotational position in physical space.
Thanks in advance, Freeze
Update 1:
I've managed to get a hold of an older Google VR APK where the fullscreen option still works and that doesn't crash, and have implemented it. So the answer to the "how to get Google VR Fullscreen" was for me: get an older version of the APK.
I'll update again once I have figured out how to get those values into the gameObject.
Update 2:
Here's how the GVR inputs go to the gameobject:
First you place the GVRMain prefab in the scene. Then you go the GVRHead gamobject and disable the child cameras, if you want to not have the view move as you move the phone around.
I've split up the axes into gimbles (empty game objects in the scene) because I want to be able to set each axis's position relative to each other. Make all of the gimble variables one object if there's only one object to rotate. Make sure that the "GVRValues" variable is the GVRHead gamobject in the scene and that should be it.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.VR;
public class CustomGoogleVR : MonoBehaviour {
[Header("Controls")]
public bool active;
[Header("Setup")]
public GameObject GVRValues;
[Header("Gimbles")]
public _Gimble yawGimble; //y-axis
public _Gimble tiltGimble; //x-axis
public _Gimble rollGimble; //z-axis
void Update() {
//Get the rotations from the HEAD prefab.
yawGimble.value = GVRValues.transform.rotation.eulerAngles.y;
tiltGimble.value = GVRValues.transform.rotation.eulerAngles.x;
rollGimble.value = GVRValues.transform.rotation.eulerAngles.z;
GameObject.FindGameObjectWithTag("GameController").GetComponent<Debugger>().Deb(yawGimble.value.ToString("0,0") + " | " + rollGimble.value.ToString("0,0") + " | " + yawGimble.value.ToString("0,0"));
//Transfer the rotation to the gimbles.
Quaternion rot = new Quaternion();
if (yawGimble.active)
{
rot = yawGimble.gimbleObject.transform.rotation;
rot.eulerAngles = new Vector3(rot.eulerAngles.x, yawGimble.value, rot.eulerAngles.z);
yawGimble.gimbleObject.transform.rotation = rot;
}
if (tiltGimble.active)
{
rot = tiltGimble.gimbleObject.transform.rotation;
rot.eulerAngles = new Vector3(tiltGimble.value, rot.eulerAngles.y, rot.eulerAngles.z);
tiltGimble.gimbleObject.transform.rotation = rot;
}
if (rollGimble.active)
{
rot = rollGimble.gimbleObject.transform.rotation;
rot.eulerAngles = new Vector3(rot.eulerAngles.x, rot.eulerAngles.y, rollGimble.value);
rollGimble.gimbleObject.transform.rotation = rot;
}
}
}
[System.Serializable]
public class _Gimble {
public GameObject gimbleObject;
public bool active;
public float value;
//public float sensitivity;
}
From here I can now experiment with turning axes on and off, and possible sensitivity for each one, as well as splitting up the axes.
Cheers.
Answer by Llama_w_2Ls · Jul 20, 2020 at 03:27 PM
To set phone rotation to a gameobject, you could use the gyroscope sensor. This allows you to rotate your screen on any of the 3 axis and see the object orientate itself to your phone angle in real time. The code for this is quite simple:
public class Gyroscope : MonoBehaviour
{
private bool gyroEnabled;
private UnityEngine.Gyroscope gyro;
private GameObject GyroControl;
public GameObject bean;
private Quaternion rot;
private void Start()
{
GyroControl = new GameObject("Gyro Control");
GyroControl.transform.position = transform.position;
transform.SetParent(GyroControl.transform); //parents the object to an empty control object
gyroEnabled = EnableGyro();
}
private bool EnableGyro()
{
if (SystemInfo.supportsGyroscope)
{
gyro = Input.gyro;
gyro.enabled = true;
GyroControl.transform.rotation = Quaternion.Euler(90f, -90f, 0f); //These offset values are essential for the gyroscope to orientate itself correctly
rot = new Quaternion(0, 0, 1, 0);
return true;
}
return false;
}
private void Update()
{
if (gyroEnabled)
{
transform.localRotation = gyro.attitude * rot;
}
}
Just attach this script to the object you want to match your phones' orientation, for example the camera, build it onto your mobile device and see the results for yourself! BTW you dont need the public gameobject 'bean'.
Your answer
Follow this Question
Related Questions
why cant I get android accelerometer working in two planes? 3 Answers
Implementing the pedometer to count step with Unity3d 2 Answers
Desperate for help on control for a ball on android phone. 1 Answer
GameObject dosen't move 2 Answers
3D: how to avoid jerks in a character movement using accelerometer 1 Answer