Switch between touchscreen and Google VR to control the Unity camera
Hey,
I'm trying to use both the touchscreen and the device-sensors to control the Unity camera in my mobile Google VR app.
Currently, i'm using the following script, on the camera, to switch between Google VR and touch navigation :
if (Input.touchCount == 1)
{
//Touch began
if (Input.GetTouch(0).phase == TouchPhase.Began)
{
//Disable device tracking
gvrHead.trackRotation = false;
//save position
firstPoint = Input.GetTouch(0).position;
xAngleTemp = xAngle;
yAngleTemp = yAngle;
}
//Move finger by screen
if (Input.GetTouch(0).phase == TouchPhase.Moved)
{
secondPoint = Input.GetTouch(0).position;
//Mainly, about rotate camera. For example, for Screen.width rotate on 180°
xAngle = xAngleTemp + (secondPoint.x - firstPoint.x) * 180.0f / Screen.width;
yAngle = yAngleTemp - (secondPoint.y - firstPoint.y) * 90.0f / Screen.height;
//Apply rotation
transform.rotation = Quaternion.Euler(-yAngle, -xAngle, 0.0f);
}
//Touch ended
if (Input.GetTouch(0).phase == TouchPhase.Ended)
{
//Enable device tracking
gvrHead.trackRotation = true;
}
}
It's working fine until on TouchPhase.Ended, when I re-enable the Google VR trackRotation, the camera is going back to the position before I disabled it.
I'm looking for something more additive : when the Google VR control is enabled back, controller position match the camera rotation (or something like this), and not the opposite (So there is no perceptible transition between touch-look and sensor-look).
I hope my intentions are clear enough, thank you for your help.
Yes @willdonohoe, I will post it there tomorrow if I have some time. It might not be the perfect solution but it's working ;)
Good stuff, I also managed to find a solution this afternoon. I can also share my findings tomorrow.
Cheers
Answer by willdonohoe · Dec 06, 2016 at 03:49 PM
Hey @bloodbc,
So my solution is also far from perfect, but I think it's good enough for my current use case. Maybe it will help others who are in a similar situation.
The name of the thing we're trying to achieve is "Magic Window", a monoscopic view, magically oriented by the gyroscope, so you can look around, but with the (common) addition of touch controls to provide additional input to the camera yaw, so the user can choose their forward facing direction without having to physically turn their body.
This was a feature of the GoogleVR SDK, but the plugin team are currently in the process of moving the sdk to run natively within Unity, rather than installing it as a plugin. Annoyingly, during this period the "Magic Window" feature has been removed from the SDK. See this issue on github .
For the time being, I had a look at using your code as a base and expanding on it to add the feature back in. You asked for a more additive approach, and I agree, doing this is probably the best way of achieving this issue, however from what I could see, the Pose3D class which is used for capturing the phone's orientation / position is pretty locked down, and I didn't want to hack into it.
What I did find out, is the GvrHead has a public "target" property, which essentially acts like a parent to the head. For example, if a body moves position or rotates, you'd expect the head to transform with it.
So I'm using the target to set the orientation when using touch movements and resetting the head position when the touch end event happens.
It's easier to explain with some code:
private GvrHead head;
private float xAngle = 0.0f;
private float yAngle = 0.0f;
private float xAngleTemp = 0.0f;
private float yAngleTemp = 0.0f;
private Vector2 firstPoint;
private Vector2 secondPoint;
private GameObject rotationTarget;
void Start() {
rotationTarget = GameObject.FindGameObjectWithTag ("rotationTarget");
// The head is added to the camera on the fly by the plugin, wait for the next frame to make sure it's been added before trying to grab it.
StartCoroutine (initiateHead ());
}
IEnumerator initiateHead() {
yield return 0;
head = gameObject.GetComponent(typeof(GvrHead)) as GvrHead;
// Set the head target with an empty game object transform.
head.target = rotationTarget.transform;
}
void Update () {
if (Input.touchCount == 1) {
if (Input.GetTouch (0).phase == TouchPhase.Began) {
// Stop the head from using the gyro.
head.trackRotation = false;
firstPoint = Input.GetTouch (0).position;
// Take the current head's local euler angles, so touch moves continues from the head's current rotation.
xAngleTemp = -head.transform.localEulerAngles.y;
yAngleTemp = -head.transform.localEulerAngles.x;
} else if (Input.GetTouch (0).phase == TouchPhase.Moved) {
secondPoint = Input.GetTouch (0).position;
xAngle = xAngleTemp + (secondPoint.x - firstPoint.x) * 180.0f / Screen.width;
yAngle = yAngleTemp - (secondPoint.y - firstPoint.y) * 90.0f / Screen.height;
transform.rotation = Quaternion.Euler (-yAngle, -xAngle, 0.0f);
// Set the rotation target rotation. Should be the same as the head rotation.
rotationTarget.transform.rotation = Quaternion.Euler (-yAngle, -xAngle, 0.0f);
} else if (Input.GetTouch (0).phase == TouchPhase.Ended) {
// After the touch has ended, recenter the head, so it should be pointing the same way as the rotation target.
vrViewer.Recenter();
// Start the gyro tracking again.
head.trackRotation = true;
}
}
}
Some extra validation should be put in there to only execute this when outside of VR mode, plus there should be something extra in place for dealing with devices in portrait.
The only other issue I'm having this current implementation, is there is a slight jump between moving with touch, and letting go. I'm not entirely sure why it happens, it shouldn't as the camera is re-centered and the target is set to the same orientation as the head.
It's also worth noting the GvrHead is listed as deprecated in their docs. So This is definitely not a long term solution. I'd imagine they will remove this when they fully integrate the SDK within Unity natively. Hopefully by this time, they would've re-integrated magic window.
So close, but not quite there :)
Your answer
Follow this Question
Related Questions
Fix rotation skipping 0 Answers
Touchscreen to Keyboard 0 Answers
Trying to make my camera rotate using gamepad 0 Answers
What is the vr head input for google vr sdk v1.130 0 Answers
Google VR SDK for Unity,Google VR SDK not setting to main camera 0 Answers