Enable/Disable 来自代码的 VR

Enable/Disable VR from code

对于部署到 Android 设备的应用程序,如何在 Unity 中以编程方式将显示设置为立体?

我想要一个 UI 菜单,用户可以在其中切换 "VR mode" 和正常模式。默认情况下我不想要 VR 模式,因为它应该是 运行 时间的一个选项。我知道在构建设置中有一个 "Virtual Reality Supported" 的设置,但我不想默认启用它。

在顶部包含 using UnityEngine.XR;

调用 XRSettings.LoadDeviceByName("") 后跟空字符串 XRSettings.enabled = false; 以在启动函数中禁用 VR 以禁用 VR。

当您想稍后启用它时,调用 XRSettings.LoadDeviceByName("daydream") 并在 VR 名称后跟 XRSettings.enabled = true;

您应该在每次函数调用之间等待一个帧。这需要完成协程功能。

此外,在某些 VR 设备上,您必须转到 编辑->项目设置->播放器 并确保 Virtual Reality Supported 复选框被 checked(true) 才能生效。然后你可以在开始功能中禁用它,并在需要时启用它。

编辑:

已知这适用于某些 VR 设备而非所有 VR 设备。虽然,它应该适用于 Daydream VR。完整代码示例:

IEnumerator LoadDevice(string newDevice, bool enable)
{
    XRSettings.LoadDeviceByName(newDevice);
    yield return null;
    XRSettings.enabled = enable;
}

void EnableVR()
{
    StartCoroutine(LoadDevice("daydream", true));
}

void DisableVR()
{
    StartCoroutine(LoadDevice("", false));
}

调用 EnableVR() 启用 vr,调用 DisableVR() 禁用它。如果您使用的不是 daydream,请将该 VR 设备的名称传递给 EnableVR() 函数中的 LoadDevice 函数。

对于较新版本的 Unity(例如 2019.4.0f1),您可以使用 XR Plugin Management 包。

启用通话:

XRGeneralSettings.Instance.Manager.InitializeLoader();

要禁用呼叫:

XRGeneralSettings.Instance.Manager.DeinitializeLoader();
 public void Awake() {
          StartCoroutine(SwitchToVR(()=>{
                Debug.Log("Switched to VR Mode");
          }));

          //For disable VR Mode
          XRSettings.enabled = false;
  }
 
  IEnumerator SwitchToVR(Action callback) {
            // Device names are lowercase, as returned by `XRSettings.supportedDevices`.
            // Google original, makes you specify
            // string desiredDevice = "daydream"; // Or "cardboard".
            // XRSettings.LoadDeviceByName(desiredDevice);
            // this is slightly better;
            
            string[] Devices = new string[] { "daydream", "cardboard" };
             XRSettings.LoadDeviceByName(Devices);
      
            // Must wait one frame after calling `XRSettings.LoadDeviceByName()`.
            yield return null;
          
            // Now it's ok to enable VR mode.
            XRSettings.enabled = true;
            callback.Invoke();
   }

2020.3.14f1

对我不起作用,我在 运行 我的 Android 应用程序时收到此错误。

Call to DeinitializeLoader without an initialized manager.Please make sure wait for initialization to complete before calling this API.

[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterAssembliesLoaded)]
        static void TryToDeinitializeOculusLoader()
        {
            XRGeneralSettings.Instance.Manager.DeinitializeLoader();
        }

更多上下文。 在他设法加载插件之前,我尝试卸载 Oculus 加载器。 我有一个 Android 应用程序,Oculus 加载程序调用 Application.Quit 因为该设备不是 Oculus 耳机。 等待 XRGeneralSettings.Instance.Manager.isInitializationComplete 的时间太长了。 尝试了所有 RuntimeInitializeLoadType 个注释。

OculusLoader.cs

    #elif (UNITY_ANDROID && !UNITY_EDITOR)
        [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterAssembliesLoaded)]
        static void RuntimeLoadOVRPlugin()
        {
            var supported = IsDeviceSupported();

            if (supported == DeviceSupportedResult.ExitApplication)
            {
                Debug.LogError("\n\nExiting application:\n\nThis .apk was built with the Oculus XR Plugin loader enabled, but is attempting to run on a non-Oculus device.\nTo build for general Android devices, please disable the Oculus XR Plugin before building the Android player.\n\n\n");
                Application.Quit();
            }

            if (supported != DeviceSupportedResult.Supported)
                return;

            try
            {
                if (!NativeMethods.LoadOVRPlugin(""))
                    Debug.LogError("Failed to load libOVRPlugin.so");
            }
            catch
            {
                // handle Android standalone build with Oculus XR Plugin installed but disabled in loader list.
            }

        }
#endif

解决方案

使我的构建 class 扩展 IPreprocessBuildWithReport

public void OnPreprocessBuild(BuildReport report)
{
    DisableXRLoaders(report);
}

///https://docs.unity3d.com/Packages/com.unity.xr.management@3.2/manual/EndUser.html
/// Do this as a setup step before you start a build, because the first thing that XR Plug-in Manager does at build time
/// is to serialize the loader list to the build target.

void DisableXRLoaders(BuildReport report)
{
    
    XRGeneralSettingsPerBuildTarget buildTargetSettings;
    EditorBuildSettings.TryGetConfigObject(XRGeneralSettings.k_SettingsKey, out buildTargetSettings);
    if (buildTargetSettings == null)
    {
        return;
    }
    
    XRGeneralSettings settings = buildTargetSettings.SettingsForBuildTarget(report.summary.platformGroup);
    if (settings == null)
    {
        return;
    }
    
    XRManagerSettings loaderManager = settings.AssignedSettings;
    
    if (loaderManager == null)
    {
        return;
    }
    
    var loaders = loaderManager.activeLoaders;
    
    // If there are no loaders present in the current manager instance, then the settings will not be included in the current build.
    if (loaders.Count == 0)
    {
        return;
    }

    var loadersForRemoval = new List<XRLoader>();
    
    loadersForRemoval.AddRange(loaders);
    
    foreach (var loader in loadersForRemoval)
    {
        loaderManager.TryRemoveLoader(loader);
    }
}

我正在使用 Unity 2021,但这可能适用于早期版本,我也在使用 XR 插件管理。

开始: XRGeneralSettings.Instance.Manager.StartSubsystems();

停止: XRGeneralSettings.Instance.Manager.StopSubsystems();

完整文档位于: https://docs.unity3d.com/Packages/com.unity.xr.management@4.0/manual/EndUser.html