Search Unity

Single "eye" render mode like the GVR plugin with VR mode disabled

Discussion in 'Daydream' started by Jeff-Rosenberg, Oct 20, 2016.

  1. Jeff-Rosenberg


    Oct 23, 2012
    Is there a way to get the native Daydream/Cardboard SDK to render to a single window, like with the GVR plugin when VR Mode is disabled?



    I want users to be able to play my game without VR by holding the device at arms-reach and using it as a "portal" to interact with the game world. This works great with the GVR plugin, but I want it to switch to native VR support so I can build the game for other VR platforms as well.

    Basically a "None" mode but with head tracking enabled.

    I'm using the 5.4.1f1-GVR8 preview.
  2. thep3000


    Unity Technologies

    Aug 9, 2013
  3. Jeff-Rosenberg


    Oct 23, 2012

    For anyone interested, the solution is to use InputTracking to get the "Center Eye" location and manually assign the position and rotation to the camera if you're in the non-VR mode.

    Code (CSharp):
    1. camTransform.localPosition = InputTracking.GetLocalPosition(VRNode.CenterEye);
    2. camTransform.localRotation = InputTracking.GetLocalRotation(VRNode.CenterEye);
    I must have glazed over those methods when searching for this.
  4. Jeff-Rosenberg


    Oct 23, 2012
    @thep3000 I've run into another problem: when I disable VR mode it seems to stretch the (left?) eye across the entire screen. It fixes itself when the phone off and then on again (side power button, not fully shut down).

    20161020_163030.jpg 20161020_163056.jpg 20161020_163107.jpg

    Any ideas?

    Edit: I seem to have solved it? Even if VR is disabled, the SDK will try and force the camera's FOV. In my case, it was picking an FOV of ~100. By resetting the FOV every frame when VR is disabled the problem goes away. Here's the code, along with the stuff for a 2D "portal" view mode:

    Updated code here.
    Last edited: Oct 21, 2016
  5. thep3000


    Unity Technologies

    Aug 9, 2013
    My guess is maybe FOV is wrong after you exit VR mode. Maybe try resetting Camera.fieldOfView / Camera.aspect and see if that helps?
  6. Jeff-Rosenberg


    Oct 23, 2012
    Yep, it's the aspect ratio. Calling camera.ResetAspect() after changing the VR settings works like a charm. Calling camera.ResetFieldOfView(), however, resets it to Unity's default 60 FOV. The SDK also seems to change the camera's FOV to ~100 before Awake is even called.


    Additionally, the FOV of the camera doesn't seem to affect the actual rendered FOV of either eye. It also doesn't seem to be set when entering VR mode, only at some point before Awake. Resetting the FOV in Awake lets the FOV during non-VR mode work as intended while letting me render VR mode correctly with it's own FOV, wherever that's set.

    I'm not really sure why the camera's FOV is changed by the SDK to begin with...

    Here's the final(ish) code, with the following features:
    • Starts in non-VR mode
      • Displays the 2D splash screen
      • On first run will be in non-VR mode
    • Continues to use "head" tracking when not in VR mode, letting the player aim with their phone at arms-length
    • Remembers which mode the player was last in
      • Cleanly switches into VR mode if appropriate after the splash screen has ended
    • Falls through to Cardboard if Daydream fails to load
    • Destroys itself (script only) if loaded onto a Gear VR device
    Just attach it to your camera and load the None "SDK" before Daydream and Cardboard.

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.VR;
    3. using System.Collections;
    5. [RequireComponent(typeof(Camera))]
    6. public class MixedVRCameraController : MonoBehaviour
    7. {
    8.     readonly string OculusDevice = "Oculus";
    9.     readonly string[] DaydreamDevices = new string[] { "daydream", "cardboard" };
    11.     [Header("Non-VR Settings")]
    12.     [SerializeField] private float fieldOfView = 60f; // Can't get the Camera's FOV because the SDK changes it even before Awake! Need our own separate slider.
    14.     #pragma warning disable 108
    15.     private Camera camera;
    16.     #pragma warning restore 108
    18.     private void Awake()
    19.     {
    20.         // Doesn't work and isn't needed with Oculus
    21.         if (VRSettings.loadedDeviceName == OculusDevice)
    22.         {
    23.             Destroy(this);
    24.             return;
    25.         }
    26.         camera = GetComponent<Camera>();
    27.         VRSettings.LoadDeviceByName(DaydreamDevices);
    28.         camera.fieldOfView = fieldOfView;
    29.     }
    31.     private void Start()
    32.     {
    33.         SetVR(PlayerPrefs.GetInt("VR Mode", 0) == 1);
    34.     }
    36.     private void Update()
    37.     {
    38.         if (!VRSettings.enabled)
    39.         {
    40.             if (Application.isEditor)
    41.             {
    42.                 transform.Rotate(0f, Input.GetAxis("Mouse X"), 0f, Space.World);
    43.                 transform.Rotate(-Input.GetAxis("Mouse Y"), 0f, 0f, Space.Self); // TODO: Stop camera from going upside down
    44.             }
    45.             else
    46.             {
    47.                 transform.localPosition = InputTracking.GetLocalPosition(VRNode.CenterEye);          
    48.                 transform.localRotation = InputTracking.GetLocalRotation(VRNode.CenterEye);
    49.             }
    50.         }
    51.     }
    53.     public void ToggleVR()
    54.     {
    55.         SetVR(!VRSettings.enabled);
    56.     }
    58.     public void SetVR(bool enabled)
    59.     {
    60.         VRSettings.enabled = enabled;
    61.         camera.ResetAspect();
    62.         PlayerPrefs.SetInt("VR Mode", enabled ? 1 : 0);
    63.     }
    64. }
    Last edited: Oct 21, 2016
    ilmario and christougher like this.
  7. sijingsijinglin


    Jun 8, 2018
    Thanks, it works!
    I saw your comment in your code, "/ TODO: Stop camera from going upside ". Did you ever figure out? I have the same problem, wondering how do you fix this.

  8. Rarceth


    Oct 15, 2015
    @sijingsijinglin The way to do this would be to store the target rotation in a variable, clamp that rotation to wanted values (lets say, -90 to 90 on the x axis, aka the up down movement), then apply. I have only ever needed to do this for FPS's, so not sure how it will go, but maybe clamp the z axis too, so the player cant roll too far? I will test :)