Created
March 14, 2025 21:20
-
-
Save DanMillerDev/2a2dd5cf3f47ede3b8c1068134003d1f to your computer and use it in GitHub Desktop.
A script for managing permissions across Apple Vision Pro, Meta Quest and Android XR. It references world space UI element to let the user know about missing or denied permissions.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using UnityEngine.XR.ARFoundation; | |
using System.Collections.Generic; | |
using TMPro; | |
using UnityEngine.Android; | |
#if UNITY_VISIONOS | |
using UnityEngine.XR.VisionOS; | |
#endif | |
public class XRPermissions : MonoBehaviour | |
{ | |
// meta quest | |
const string k_MetaScenePermissionId = "com.oculus.permission.USE_SCENE"; | |
const string k_MetaHandPermissionId = "com.oculus.permission.HAND_TRACKING"; | |
// android xr | |
const string k_AndroidXRSceneMinPermissionId = "android.permission.SCENE_UNDERSTANDING_COARSE"; | |
const string k_AndroidXRSceneMaxPermissionId = "android.permission.SCENE_UNDERSTANDING_FINE"; | |
const string k_AndroidXRHandPermissionId = "android.permission.HAND_TRACKING"; | |
[SerializeField] | |
ARPlaneManager m_PlaneManager; | |
[SerializeField] | |
HandTrackingManager m_HandManager; | |
[SerializeField] | |
GameObject m_DeniedPermissionsPopup; | |
[SerializeField] | |
TMP_Text m_DeniedPermissionsText; | |
#if UNITY_VISIONOS | |
void OnEnable() | |
{ | |
VisionOS.AuthorizationChanged += OnAuthorizationChanged; | |
} | |
void OnDisable() | |
{ | |
VisionOS.AuthorizationChanged -= OnAuthorizationChanged; | |
} | |
void UpdateAuthorizationText() | |
{ | |
var type = VisionOSAuthorizationType.HandTracking; | |
var status = VisionOS.QueryAuthorizationStatus(type); | |
OnAuthorizationChanged(new VisionOSAuthorizationEventArgs { type = type, status = status }); | |
type = VisionOSAuthorizationType.WorldSensing; | |
status = VisionOS.QueryAuthorizationStatus(type); | |
OnAuthorizationChanged(new VisionOSAuthorizationEventArgs { type = type, status = status }); | |
} | |
void OnAuthorizationChanged(VisionOSAuthorizationEventArgs args) | |
{ | |
switch (args.type) | |
{ | |
case VisionOSAuthorizationType.HandTracking: | |
if (args.status == VisionOSAuthorizationStatus.Denied) | |
{ | |
m_DeniedPermissionsText.text += "Hand permission \n"; | |
} | |
break; | |
case VisionOSAuthorizationType.WorldSensing: | |
if (args.status == VisionOSAuthorizationStatus.Denied) | |
{ | |
m_DeniedPermissionsText.text += "Scene permission \n"; | |
} | |
break; | |
// We do not support CameraAccess yet so ignore it | |
} | |
m_DeniedPermissionsPopup.SetActive(true); | |
} | |
#endif | |
void Start() | |
{ | |
var permissions = new List<string>(); | |
m_DeniedPermissionsText.text = ""; | |
#if UNITY_META_QUEST | |
// add permissions that have not been granted by the user | |
if (!Permission.HasUserAuthorizedPermission(k_MetaScenePermissionId)) | |
{ | |
permissions.Add(k_MetaScenePermissionId); | |
} | |
else | |
{ | |
// enable the AR Plane Manager component if permission is already granted | |
m_PlaneManager.enabled = true; | |
} | |
if (!Permission.HasUserAuthorizedPermission(k_MetaHandPermissionId)) | |
{ | |
permissions.Add(k_MetaHandPermissionId); | |
} | |
else | |
{ | |
m_HandManager.enabled = true; | |
} | |
#elif UNITY_ANDROID_XR | |
// add permissions that have not been granted by the user | |
if(!Permission.HasUserAuthorizedPermission(k_AndroidXRSceneMinPermissionId)) | |
{ | |
permissions.Add(k_AndroidXRSceneMinPermissionId); | |
} | |
else | |
{ | |
m_PlaneManager.enabled = true; | |
} | |
if(!Permission.HasUserAuthorizedPermission(k_AndroidXRHandPermissionId)) | |
{ | |
permissions.Add(k_AndroidXRHandPermissionId); | |
} | |
else | |
{ | |
m_HandManager.enabled = true; | |
} | |
#elif UNITY_VISIONOS | |
UpdateAuthorizationText(); | |
#endif | |
// setup callbacks to be called depending on whether permission is granted | |
var callbacks = new PermissionCallbacks(); | |
callbacks.PermissionDenied += OnPermissionDenied; | |
callbacks.PermissionGranted += OnPermissionGranted; | |
Permission.RequestUserPermissions(permissions.ToArray(), callbacks); | |
} | |
void OnPermissionDenied(string permission) | |
{ | |
// handle denied permission | |
Debug.LogError($"Permission {permission} was denied by the user"); | |
// show a popup to inform the user that the permission is required | |
if(permission == k_MetaScenePermissionId || permission == k_AndroidXRSceneMinPermissionId) | |
{ | |
m_DeniedPermissionsText.text += "Scene permission \n"; | |
} | |
if(permission == k_MetaHandPermissionId || permission == k_AndroidXRHandPermissionId) | |
{ | |
m_DeniedPermissionsText.text += "Hand permission \n"; | |
} | |
m_DeniedPermissionsPopup.SetActive(true); | |
} | |
void OnPermissionGranted(string permission) | |
{ | |
// enable the corresponding AR Manager component after required permission is granted | |
if (permission == k_MetaScenePermissionId || permission == k_AndroidXRSceneMinPermissionId) | |
{ | |
m_PlaneManager.enabled = true; | |
} | |
if(permission == k_MetaHandPermissionId || permission == k_AndroidXRHandPermissionId) | |
{ | |
m_HandManager.enabled = true; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment