I am trying to build some logic to test the device after app start to decide whether to allow for AR scene or only conventional 3D scene.
I know we can use ARSubsystemManager.systemState to check that but this works only when AR Session component is present in the scene, which means that there needs to be an attempt to initialize AR Session.
This is pretty expensive task that I would like to avoid straight after launching the app.
On Android, the availability check can take several frames because if ARCore is not installed already (or the app the requires a newer version of ARCore), then it has to check with the Play Store to see if there is a version of ARCore which supports that particular device.
Note that when deploying an ARCore required app from Unity (e.g., click āBuild and Runā), unsupported devices will be reported as supported because the Play Store would not have allowed the app to be installed on an unsupported device in the first place.
Thanks Tim, I tried ARSubsystemManager.checkAvailability() in a coroutine but is doesnāt work unless AR Session is initilized - systemState is returning āUnsupportedā. When checking systemState in AR-enabled scene it works ok.
I guess it is due to these lines of code inside ARSubsystemManager.checkAvailability():
if (sessionSubsystem == null)
{
systemState = ARSystemState.Unsupported;
}
For me this means you need to try to initialize AR Session first to check whether it will work.
Of course I am considering this for an āAR-optionalā app, where depending on the device compatibility the user is given either 3D-only or 3D+AR options.
You shouldnāt need to destroy it in your case since you are about to start an AR scene. It is safe to call ARSubsystemManager.CreateSubsystems() multiple times (the second time is effectively a no-op).
If you did not immediately start your AR scene, then you might want to call DestroySubsystems just to make sure you cleanly shut down the AR session.
I have my ARCore Optional app working on devices that do not support arcore etc. And use the above logic to enable AR within my game.
How would I do same for IOS? Such that my app will be made available to all devices running target IOS ver 11⦠whether they support ARKit or not⦠and then allow the logic above to control enabling/disabling AR within my game.
I tried the āChecking for Device Supportā available in the documentation of AR Foundation package. It works in case of supported devices, but in case of unsupported devices it throws below exception and the ARSession.state gets set to āNoneā:
E/Unity: DllNotFoundException: UnityARCore
at (wrapper managed-to-native) UnityEngine.XR.ARCore.ARCoreSessionSubsystem+NativeApi.UnityARCore_session_construct(UnityEngine.XR.ARCore.ARCoreSessionSubsystem/NativeApi/CameraPermissionRequestProviderDelegate)
at UnityEngine.XR.ARCore.ARCoreSessionSubsystem+Providerā¦ctor (UnityEngine.XR.ARCore.ARCoreSessionSubsystem subsystem) [0x0000d] in <6d08a2168eb04129816197a2388b8f39>:0
at UnityEngine.XR.ARCore.ARCoreSessionSubsystem.CreateProvider () [0x00000] in <6d08a2168eb04129816197a2388b8f39>:0
at UnityEngine.XR.ARSubsystems.XRSessionSubsystemā¦ctor () [0x00006] in <9721d2a78fbe4e8db7471dffc3f5f1ba>:0
at UnityEngine.XR.ARCore.ARCoreSessionSubsystemā¦ctor () [0x00000] in <6d08a2168eb04129816197a2388b8f39>:0
at (wrapper managed-to-native) System.Reflection.MonoCMethod.InternalInvoke(System.Reflection.MonoCMethod,object,object[ ],System.Exception&)
at System.Reflection.MonoCMethod.InternalInvoke (System.Object obj, System.Object[ ] parameters) [0x00002] in <c044b3
I am using Unity 2019.1.11, AR Foundation 2.1.1 and I am checking it using below co routine:
private IEnumerator CheckAvailability()
{
Debug.Log("ARSession.state: " + ARSession.state);
if ((ARSession.state == ARSessionState.None) ||
(ARSession.state == ARSessionState.CheckingAvailability))
{
ShowErrorMessage("Started Checking Availability...");
yield return ARSession.CheckAvailability();
}
Debug.Log("ARSession.state: " + ARSession.state);
switch (ARSession.state)
{
case ARSessionState.Ready:
Debug.Log("Supported and installed");
LoadARCoreScene();
break;
case ARSessionState.NeedsInstall:
Debug.Log("Supported, not installed, requesting installation");
LoadARCoreScene();
break;
case ARSessionState.Installing:
Debug.Log("Supported apk installing");
LoadARCoreScene();
break;
default:
Debug.Log("Unsupported Device Not Capable");
LoadNonARCoreScene();
break;
}
}
hey @thesanketkale
I found signing up to ARSession.stateChanged += ARState; at start worked well for me, also running coroutine CheckARSupportedByMobile at start. hope it helps, cheers
IEnumerator CheckARSupportedByMobile()
{
Debug.Log("State " + ARSession.state);
if ((ARSession.state == ARSessionState.None || ARSession.state == ARSessionState.CheckingAvailability))
{
Debug.Log("Checking AR Availability on mobile device");
yield return ARSession.CheckAvailability();
}
}
public void ARState(ARSessionStateChangedEventArgs e)
{
switch (ARSession.state)
{
case ARSessionState.None:
case ARSessionState.CheckingAvailability:
Debug.Log("AR Session - Looking for availability");
break;
case ARSessionState.Unsupported:
Debug.Log("AR Session - not available to this mobile device");
break;
case ARSessionState.NeedsInstall:
m_Session.enabled = true;
Debug.Log("AR Session - needs to be installed in mobile device ");
break;
case ARSessionState.Installing:
m_Session.enabled = true;
Debug.Log("AR Session - Installing AR onto mobile device ");
break;
case ARSessionState.Ready:
m_Session.enabled = true;
Debug.Log("AR Session - supported by mobile device and ready to fire up ");
break;
case ARSessionState.SessionInitializing:
m_Session.enabled = true;
Debug.Log("AR session is initializing ");
break;
case ARSessionState.SessionTracking:
Debug.Log("AR Session is tracking");
break;
default:
Debug.Log("AR Session - no switch worked");
break;
}
}
Firstly I must say, thank you for replying. Just after your response, I thought that if the same code was working for you, I must have been doing something wrong in my splash scene or player settings. Thatās where I figured out that I had added ARSession prefab in my splash screen scene where I was checking the ARCore availability. I had added it thinking that while using ARSession.CheckAvailability() the ARSession object might need initialization via a gameobject in the scene. But apparently I was mistaken as CheckAvailability() being a static coroutine, does not need the ARSession to be initialized. The ARSession script on the ARSession prefab in the scene was actually throwing the exception and not ARSession.CheckAvailability().
Having removed the ARSession prefab from the splash screen, the ARSession.CheckAvailability() is setting the correct ARSessionState now. Thanks again for the reply.
I am getting unsupported when ground plane works⦠does this work with vuforia? Iām trying to use arfoundation just to check if the device has arcore, becuase vuforiaās
VuforiaRuntimeUtilities.GetActiveFusionProvider isnāt working eitherā¦
Iām desperate hereā¦