Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

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

    Jeff-Rosenberg

    Joined:
    Oct 23, 2012
    Posts:
    26
    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?

    Off.PNG

    On.PNG

    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

    thep3000

    Unity Technologies

    Joined:
    Aug 9, 2013
    Posts:
    400
  3. Jeff-Rosenberg

    Jeff-Rosenberg

    Joined:
    Oct 23, 2012
    Posts:
    26
    Thanks!

    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

    Jeff-Rosenberg

    Joined:
    Oct 23, 2012
    Posts:
    26
    @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

    thep3000

    Unity Technologies

    Joined:
    Aug 9, 2013
    Posts:
    400
    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

    Jeff-Rosenberg

    Joined:
    Oct 23, 2012
    Posts:
    26
    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.

    Capture.PNG

    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;
    4.  
    5. [RequireComponent(typeof(Camera))]
    6. public class MixedVRCameraController : MonoBehaviour
    7. {
    8.     readonly string OculusDevice = "Oculus";
    9.     readonly string[] DaydreamDevices = new string[] { "daydream", "cardboard" };
    10.  
    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.
    13.  
    14.     #pragma warning disable 108
    15.     private Camera camera;
    16.     #pragma warning restore 108
    17.  
    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.     }
    30.  
    31.     private void Start()
    32.     {
    33.         SetVR(PlayerPrefs.GetInt("VR Mode", 0) == 1);
    34.     }
    35.  
    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.     }
    52.  
    53.     public void ToggleVR()
    54.     {
    55.         SetVR(!VRSettings.enabled);
    56.     }
    57.  
    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
    Edisyo, ilmario and christougher like this.
  7. sijingsijinglin

    sijingsijinglin

    Joined:
    Jun 8, 2018
    Posts:
    2
    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

    Rarceth

    Joined:
    Oct 15, 2015
    Posts:
    41
    @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 :)
     
  9. Edisyo

    Edisyo

    Joined:
    Dec 11, 2017
    Posts:
    9
    Thanks, works like a charm in 2019.1.8f1!

     
  10. HelmiHNuW

    HelmiHNuW

    Joined:
    Oct 19, 2019
    Posts:
    5
    Excuse me sir, do you user the GoogleVR pakage? And where should I apply the script? Thanks
     
  11. HelmiHNuW

    HelmiHNuW

    Joined:
    Oct 19, 2019
    Posts:
    5
    Would you tell me where to apply the script? I use the GVR and planned to make it not splitting into two side
     
  12. eganki

    eganki

    Joined:
    May 13, 2014
    Posts:
    1

    Just incase someone need this for newer version of Unity( > 2019.2.8f1)
    This is my code for my google cardboard with some modifications
    Special thanks for Jeff for his awesome guides
    and credit to this link too~
    https://forum.unity.com/threads/updating-from-getlocalrotation-to-getnodestates.695527/


    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.XR;
    3. using System.Collections;
    4.  
    5. [RequireComponent(typeof(Camera))]
    6. public class CameraView : MonoBehaviour
    7. {
    8.     readonly string CardboardDevices = "cardboard";
    9.  
    10.     [Header("Non-VR Settings")]
    11.     [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.
    12.  
    13. #pragma warning disable 108
    14.     private Camera camera;
    15. #pragma warning restore 108
    16.  
    17.     private void Awake()
    18.     {
    19.         camera = GetComponent<Camera>();
    20.         XRSettings.LoadDeviceByName(CardboardDevices);
    21.         camera.fieldOfView = fieldOfView;
    22.      
    23.     }
    24.  
    25.     private void Update()
    26.     {
    27.         if (!XRSettings.enabled)
    28.         {
    29.             if (TryGetCenterEyePosition(out Vector3 _position))
    30.             {
    31.                 transform.localPosition = _position;
    32.             }
    33.             if (TryGetCenterEyeFeature(out Quaternion _rotation))
    34.             {
    35.                 transform.localRotation = _rotation;
    36.             }
    37.         }
    38.     }
    39.  
    40.     bool TryGetCenterEyeFeature(out Quaternion _rotation)
    41.     {
    42.         InputDevice device = InputDevices.GetDeviceAtXRNode(XRNode.CenterEye);
    43.         if (device.isValid)
    44.         {
    45.             if (device.TryGetFeatureValue(CommonUsages.centerEyeRotation, out _rotation))
    46.                 return true;
    47.         }
    48.         // This is the fail case, where there was no center eye was available.
    49.         _rotation = Quaternion.identity;
    50.         return false;
    51.     }
    52.     bool TryGetCenterEyePosition(out Vector3 _position)
    53.     {
    54.         InputDevice device = InputDevices.GetDeviceAtXRNode(XRNode.CenterEye);
    55.         if (device.isValid)
    56.         {
    57.             if (device.TryGetFeatureValue(CommonUsages.centerEyePosition, out _position))
    58.                 return true;
    59.         }
    60.         // This is the fail case, where there was no center eye was available.
    61.         _position = transform.localPosition;
    62.         return false;
    63.     }
    64. }
     
    Last edited: Jan 8, 2020
    DaneyT and christougher like this.