Search Unity

Resolved Dynamically rearrange Cardboard and ARFoundation plugin providers?

Discussion in 'AR' started by rob11, May 25, 2021.

  1. rob11

    rob11

    Joined:
    Mar 7, 2017
    Posts:
    59
    Hello, I have a project in which I need ARFoundation (ARCore, currently testing on Android) and Google Cardboard working in different scenes. They will never be used at the same time.

    When I only include the Cardboard plugin providers in XR Management in Project Settings, the VR works fine. But when I add ARCore plugin provider (With ARCore and depth set to optional). My google cardboard stops working. It feels like they are incompatible or the apk is only loading the ARCore plugin.

    Is there a way to make sure Google Cardboard and ARCore plugin providers are enabled ?
    I would like to handle these dynamically, and disable ARCore altogether when it is not needed, same for Cardboard.

    Thank you, any help is appreciated :)

    upload_2021-5-25_16-5-13.png
     
  2. rob11

    rob11

    Joined:
    Mar 7, 2017
    Posts:
    59
    After researching this, I can confirm that the XR Plugins Manager iterates through the list of Checked Plug-in Providers (loaders) and stops when it successfully initialize a loader. It iterates through it alphabetically. There is no supported way of dynamically loading/unloading specific loaders, which is sad.

    This doesn't mean you cannot achieve this ! You can change XR Plugin management code to support this.

    First, make sure you XR Plugin management package as been copied to your packages folder, so you can modify it without it reverting back.

    You then have to modify XRManagerSettings class to make the active loader public. It is the variable we are going to use from our custom script.


    ///<summary>
    /// Return the current singleton active loader instance.
    ///</summary>
    [HideInInspector] public XRLoader activeLoader;


    Then you have to remember your loaders order.

    upload_2021-5-26_18-7-56.png

    Then a custom script I've made to interact with the unity XR Plug-in Management :

    Code (CSharp):
    1. using System;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5. using UnityEngine.SceneManagement;
    6. using UnityEngine.XR.Management;
    7.  
    8. public class CustomXRToggler : MonoBehaviour
    9. {
    10.     [SerializeField] private int _mainMenuSceneIndex = 0;
    11.     [SerializeField] private int _carboardSceneIndex;
    12.     [SerializeField] private int _arSceneIndex;
    13.  
    14.     public void StartXR(XRExperience loaderToActivate)
    15.     {
    16.         StartCoroutine(COROUTINE_StartXR(loaderToActivate));
    17.     }
    18.  
    19.     public void StopXR(XRExperience loaderToStop)
    20.     {
    21.         StartCoroutine(COROUTINE_StopXR(loaderToStop));
    22.     }
    23.  
    24.     private IEnumerator COROUTINE_StopXR(XRExperience loaderToStop)
    25.     {
    26.         XRGeneralSettings.Instance.Manager.StopSubsystems();
    27.  
    28.         yield return XRGeneralSettings.Instance.Manager.loaders[(int)loaderToStop].Deinitialize();
    29.      
    30.         XRGeneralSettings.Instance.Manager.loaders[(int)loaderToStop].Stop();
    31.         XRGeneralSettings.Instance.Manager.activeLoader = null;
    32.  
    33.         SceneManager.LoadScene(_mainMenuSceneIndex);
    34.     }
    35.  
    36.     private IEnumerator COROUTINE_StartXR(XRExperience loaderToActivate)
    37.     {
    38.         yield return XRGeneralSettings.Instance.Manager.loaders[(int)loaderToActivate].Initialize();
    39.  
    40.         XRGeneralSettings.Instance.Manager.activeLoader = XRGeneralSettings.Instance.Manager.loaders[(int)loaderToActivate];
    41.  
    42.         XRGeneralSettings.Instance.Manager.loaders[(int)loaderToActivate].Start();
    43.  
    44.         if (XRGeneralSettings.Instance.Manager.activeLoader == null)
    45.         {
    46.             Debug.LogError("Initializing XR Failed. Check Editor or Player log for details.");
    47.         }
    48.         else
    49.         {
    50.             Debug.Log("Starting XR...");
    51.             XRGeneralSettings.Instance.Manager.StartSubsystems();
    52.             yield return null;
    53.             switch (loaderToActivate)
    54.             {
    55.                 case XRExperience.ARCore:
    56.                     SceneManager.LoadScene(_arSceneIndex);
    57.                     break;
    58.                 case XRExperience.GoogleCardboard:
    59.                     SceneManager.LoadScene(_carboardSceneIndex);
    60.                     break;
    61.                 default:
    62.                     throw new ArgumentOutOfRangeException(nameof(loaderToActivate), loaderToActivate, null);
    63.             }
    64.         }
    65.     }
    66. }
    67.  
    68. public enum XRExperience
    69. {
    70.     ARCore,
    71.     GoogleCardboard
    72. }
    I've used an enum to make it clearer what numbers refered to what plugins. But you have to be careful since this will change if you use different plugins. You just have to follow the alphabetical order of all checked box from 0. Also you'll have to use platform specific code if you were to deploy to IOS because it could have different plugins and order.

    You now simply have to call startXR and stopXR and pass the loader you want to start/stop. As far as I tested, you can only have 1 loader active at any given time, so make sure to stop the previous loader before activating another one.

    Really hope this helps someone as I've researched this for a long time.
     
    Last edited: Jun 9, 2021