#if USING_META_OCCLUSION && (UNITY_ANDROID || UNITY_EDITOR) #define META_OCCLUSION_AVAILABLE using UnityEngine.XR.OpenXR.Features.Meta; using UnityEngine.XR.OpenXR.NativeTypes; #endif using UnityEngine.XR.ARFoundation; using UnityEngine.XR.ARSubsystems; namespace UnityEngine.XR.Templates.MR { /// /// Utility class that provides configuration for occlusion support. /// public class OcclusionManager : MonoBehaviour { [SerializeField, Tooltip("Enable the occlusion manager on start.")] bool m_EnableManagerOnStart = false; /// /// Enable the occlusion manager on start. /// public bool enableManagerOnStart { get => m_EnableManagerOnStart; set => m_EnableManagerOnStart = value; } [SerializeField, Tooltip("The UI Toggle GameObject that will be disabled if occlusion is not supported.")] GameObject m_UIToggleObject; /// /// The UI Toggle GameObject that will be disabled if occlusion is not supported. /// public GameObject uiToggleObject { get => m_UIToggleObject; set => m_UIToggleObject = value; } [SerializeField, Tooltip("The GameObject containing the Quest-specific settings.")] GameObject m_QuestSettings; /// /// The GameObject containing the Quest-specific settings. /// public GameObject questSettings { get => m_QuestSettings; set => m_QuestSettings = value; } [SerializeField, Tooltip("The GameObject containing the Android XR-specific settings.")] GameObject m_AndroidXRSettings; /// /// The GameObject containing the Android XR-specific settings. /// public GameObject AndroidXRSettings { get => m_AndroidXRSettings; set => m_AndroidXRSettings = value; } AROcclusionManager m_AROcclusionManager; ARShaderOcclusion m_ARShaderOcclusion; void Start() { if (TrySetupOcclusion() && m_EnableManagerOnStart) { SetupManager(); } } bool TrySetupOcclusion() { // Check if the platform supports occlusion if (LoaderUtility .GetActiveLoader()? .GetLoadedSubsystem() != null) { // XROcclusionSubsystem was loaded. The platform supports occlusion. m_AROcclusionManager = FindAnyObjectByType(); if (m_AROcclusionManager == null) { Debug.LogWarning("No AROcclusionManager found, yet Use Occlusion is enabled. Disabling Object.", this); m_UIToggleObject.SetActive(false); return false; } else { if (!m_AROcclusionManager.gameObject.TryGetComponent(out m_ARShaderOcclusion)) { Debug.LogWarning($"No {nameof(ARShaderOcclusion)} component found. Adding one manually now.", this); m_ARShaderOcclusion = m_AROcclusionManager.gameObject.AddComponent(); } } SetupDeviceSpecificSettings(); return true; } // If the platform does not support occlusion, disable the object else { Debug.LogWarning("Occlusion is not supported on this platform. Disabling Object.", this); m_UIToggleObject.SetActive(false); return false; } } /// /// Sets up device-specific settings for the occlusion manager. /// This is called in the Start method to ensure that the correct settings are applied based on the current XR platform. /// This function is important for ensuring that the occlusion manager works correctly on different devices based on the platform specifics. /// void SetupDeviceSpecificSettings() { Debug.Log($"Current XR Platform: {XRPlatformUnderstanding.CurrentPlatform}"); switch (XRPlatformUnderstanding.CurrentPlatform) { case XRPlatformType.Quest: m_QuestSettings.SetActive(true); m_AndroidXRSettings.SetActive(false); break; case XRPlatformType.AndroidXR: m_QuestSettings.SetActive(false); m_AndroidXRSettings.SetActive(true); m_AROcclusionManager.environmentDepthTemporalSmoothingRequested = true; SetShaderMode(AROcclusionShaderMode.HardOcclusion); break; case XRPlatformType.Other: m_QuestSettings.SetActive(false); m_AndroidXRSettings.SetActive(false); break; } } /// /// Sets up the occlusion manager and enables it if necessary. /// This is called from the goal manager to ensure that the occlusion manager is set up correctly and enabled when needed. /// public void SetupManager() { if (m_AROcclusionManager != null && !m_AROcclusionManager.enabled) m_AROcclusionManager.enabled = true; if (m_ARShaderOcclusion != null && !m_ARShaderOcclusion.enabled) m_ARShaderOcclusion.enabled = true; } /// /// Sets the occlusion manager to be enabled or disabled. /// This is called from the UI toggle to enable or disable the occlusion manager based on user input. /// /// Enables or disables based on value. public void SetOcclusionIsOn(bool isOn) { if (m_AROcclusionManager != null) { m_AROcclusionManager.enabled = isOn; } } /// /// Sets the shader mode for the occlusion manager. /// This is called from the UI dropdown to set the shader mode based on user input. /// /// The shader mode to set for the occlusion manager. /// /// The shader mode is an integer value that corresponds to the enum. /// The value is offset by 1 because the first value in the enum is None, which is not used in this context. /// public void SetShaderMode(int shaderMode) { // Offset by 1 because we don't use None SetShaderMode((AROcclusionShaderMode)(++shaderMode)); } void SetShaderMode(AROcclusionShaderMode mode) { if (m_ARShaderOcclusion != null) { m_ARShaderOcclusion.occlusionShaderMode = mode; Debug.Log("Setting shader mode to " + mode); } } /// /// Sets the state of temporal smoothing for the . /// /// If true, temporal smoothing will be applied to the environment depth image. public void SetTemporalSmoothingEnabled(bool isEnabled) { if (m_AROcclusionManager != null) { m_AROcclusionManager.environmentDepthTemporalSmoothingRequested = isEnabled; } } /// /// Sets the hand removal feature for the Meta OpenXR occlusion subsystem. /// /// Sets the Hand Removal Feature value. public void SetHandHandRemovalEnabled(bool isEnabled) { #if META_OCCLUSION_AVAILABLE var subsystem = m_AROcclusionManager.subsystem as MetaOpenXROcclusionSubsystem; var result = subsystem.TrySetHandRemovalEnabled(isEnabled); if (result.IsError()) { // Handle error Debug.LogWarning("Error setting hand removal enabled: " + result.ToString()); } #endif } } }