# Building hybrid apps in Unity

Hybrid apps support both 2D (non-VR) and VR modes.

- Developers can choose whether a hybrid app starts in 2D or in VR mode.
  However, Daydream apps must be configured to start in VR mode when launched
  from Daydream home.

- Developers are responsible for providing users a way to switch
  between modes.

- While in 2D, apps can optionally allow users to preview content inside a
  [Magic Window](https://developers.google.com/vr/develop/unity/guides/magic-window) view, which may
  or may not be full screen.

## Prerequisites

To enable switching between 2D and VR at runtime in your app:

1. Ensure **Player Settings \> Android/iOS \> Virtual Reality Supported** is
   checked.

2. Add the following entries in **Player Settings \> Android/iOS \> Virtual
   Reality SDKs**:

   - Add **None** to support 2D mode in your app.

   - Add **Daydream** and/or **Cardboard** to support VR mode in your app.

3. Order the SDK options to control which mode your app starts in when
   launched from the 2D desktop launcher:

   - To start in 2D mode, put **None** first.

   - To start in VR mode, put **Daydream** or **Cardboard** first.

## Switching to VR mode at runtime

To enter VR mode at runtime, load the desired VR device, wait one frame, then
enable VR mode. Here is an example:

    // Call via `StartCoroutine(SwitchToVR())` from your code. Or, use
    // `yield SwitchToVR()` if calling from inside another coroutine.
    IEnumerator SwitchToVR() {
      // Device names are lowercase, as returned by `XRSettings.supportedDevices`.
      string desiredDevice = "daydream"; // Or "cardboard".

      // Some VR Devices do not support reloading when already active, see
      // https://docs.unity3d.com/ScriptReference/XR.XRSettings.LoadDeviceByName.html
      if (String.Compare(XRSettings.loadedDeviceName, desiredDevice, true) != 0) {
        XRSettings.LoadDeviceByName(desiredDevice);

        // Must wait one frame after calling `XRSettings.LoadDeviceByName()`.
        yield return null;
      }

      // Now it's ok to enable VR mode.
      XRSettings.enabled = true;
    }

## Switching to 2D mode at runtime

To leave VR mode at runtime, load the "None" device, wait one frame, then reset
camera transform and settings. Here is an example:

    // Call via `StartCoroutine(SwitchTo2D())` from your code. Or, use
    // `yield SwitchTo2D()` if calling from inside another coroutine.
    IEnumerator SwitchTo2D() {
      // Empty string loads the "None" device.
      XRSettings.LoadDeviceByName("");

      // Must wait one frame after calling `XRSettings.LoadDeviceByName()`.
      yield return null;

      // Not needed, since loading the None (`""`) device takes care of this.
      // XRSettings.enabled = false;

      // Restore 2D camera settings.
      ResetCameras();
    }

    // Resets camera transform and settings on all enabled eye cameras.
    void ResetCameras() {
      // Camera looping logic copied from GvrEditorEmulator.cs
      for (int i = 0; i < Camera.allCameras.Length; i++) {
        Camera cam = Camera.allCameras[i];
        if (cam.enabled && cam.stereoTargetEye != StereoTargetEyeMask.None) {

          // Reset local position.
          // Only required if you change the camera's local position while in 2D mode.
          cam.transform.localPosition = Vector3.zero;

          // Reset local rotation.
          // Only required if you change the camera's local rotation while in 2D mode.
          cam.transform.localRotation = Quaternion.identity;

          // No longer needed, see issue github.com/googlevr/gvr-unity-sdk/issues/628.
          // cam.ResetAspect();

          // No need to reset `fieldOfView`, since it's reset automatically.
        }
      }
    }

## Detecting whether your app was launched from VR

Daydream apps can be launched from VR or from the 2D launcher. See the
[Android Manifest for Google VR](https://developers.google.com/vr/reference/vr-manifest#platform_compatibility)
reference for a list of supported Android intent filters that enable launching
from VR or 2D.

Unity ensures that hybrid Daydream apps launched from VR automatically start in
VR mode, even if the **None** device is listed above the **Daydream** VR device
in **Player Settings \> Android/iOS \> Virtual Reality SDKs** .
This helps ensure that your app meets Daydream design requirement
[UX-D9](https://developers.google.com/vr/distribute/daydream/design-requirements#UX-D9).

To detect whether your app was launched from VR at runtime, use
[`GvrIntent.IsLaunchedFromVr()`](https://developers.google.com/vr/reference/unity/class/GvrIntent#classGvrIntent_1a66212d583253e0dca3bd00cc563d3739).
This method returns `true` if the Android intent
that launched your app contains the `android.intent.extra.VR_LAUNCH` extra,
indicating that your app was launched from VR.