using System; using System.Collections.Generic; using UnityEngine.XR.ARSubsystems; using Unity.XR.CoreUtils; namespace UnityEngine.XR.ARFoundation { /// /// A manager for s. Uses the XRObjectTrackingSubsystem /// to recognize and track 3D objects in the physical environment. /// /// /// Related information: AR Tracked Object Manager component /// [DefaultExecutionOrder(ARUpdateOrder.k_TrackedObjectManager)] [DisallowMultipleComponent] [RequireComponent(typeof(XROrigin))] [AddComponentMenu("XR/AR Foundation/AR Tracked Object Manager")] [HelpURL("features/object-tracking")] public sealed class ARTrackedObjectManager : ARTrackableManager< XRObjectTrackingSubsystem, XRObjectTrackingSubsystemDescriptor, XRObjectTrackingSubsystem.Provider, XRTrackedObject, ARTrackedObject> { [SerializeField] [Tooltip("The library of objects which will be detected and/or tracked in the physical environment.")] XRReferenceObjectLibrary m_ReferenceLibrary; /// /// The ARObjectLibrary to use during object detection. This is the /// library of objects which will be detected and tracked in the physical environment. /// public XRReferenceObjectLibrary referenceLibrary { get => m_ReferenceLibrary; set { m_ReferenceLibrary = value; UpdateReferenceObjects(); if (subsystem != null) { subsystem.library = m_ReferenceLibrary; } } } [SerializeField] [Tooltip("If not null, instantiates this prefab for each detected object.")] GameObject m_TrackedObjectPrefab; /// /// If not null, instantiates this Prefab for each detected object. /// public GameObject trackedObjectPrefab { get => m_TrackedObjectPrefab; set => m_TrackedObjectPrefab = value; } /// /// Get the Prefab to instantiate for each . /// /// The prefab to instantiate for each . protected override GameObject GetPrefab() => m_TrackedObjectPrefab; /// /// Invoked once per frame with information about the s that have changed (that is, been added, updated, or removed). /// This happens just before s are destroyed, so you can set ARTrackedObject.destroyOnRemoval to false /// from this event to suppress this behavior. /// [Obsolete("trackedObjectsChanged has been deprecated in AR Foundation version 6.0. Use trackablesChanged instead.", false)] public event Action trackedObjectsChanged; /// /// The name to be used for the GameObject whenever a new object is detected. /// protected override string gameObjectName => "ARTrackedObject"; /// /// Sets the object library on the subsystem before Start() is called on the base class. /// protected override void OnBeforeStart() { UpdateReferenceObjects(); if (referenceLibrary != null) { subsystem.library = referenceLibrary; } else { enabled = false; #if DEVELOPMENT_BUILD Debug.LogWarning($"{nameof(ARTrackedObjectManager)} '{name}' was enabled but no reference object library is specified. To enable, set a valid reference object library and then re-enable this component."); #endif } } /// /// Invoked just after each has been updated. /// /// The being updated. /// New data associated with . /// All spatial data is relative to the . protected override void OnAfterSetSessionRelativeData( ARTrackedObject trackedObject, XRTrackedObject sessionRelativeData) { if (m_ReferenceLibrary != null && m_ReferenceObjectCount != m_ReferenceLibrary.count) { // Since reference libraries can change, make sure // our reference object dictionary is up to date. UpdateReferenceObjects(); } var guid = sessionRelativeData.referenceObjectGuid; if (!m_ReferenceObjects.TryGetValue(guid, out var referenceObject)) { Debug.LogError($"Could not find reference object with guid {guid}"); } trackedObject.referenceObject = referenceObject; } /// /// Invokes the event. /// /// A list of objects added this frame. /// A list of objects updated this frame. /// A list of objects removed this frame. [Obsolete("OnTrackablesChanged() has been deprecated in AR Foundation version 6.0.", false)] protected override void OnTrackablesChanged( List added, List updated, List removed) { if (trackedObjectsChanged != null) { using (new ScopedProfiler("OnTrackedObjectsChanged")) trackedObjectsChanged?.Invoke( new ARTrackedObjectsChangedEventArgs( added, updated, removed)); } } void UpdateReferenceObjects() { m_ReferenceObjects.Clear(); m_ReferenceObjectCount = 0; if (m_ReferenceLibrary == null) return; foreach (var referenceObject in m_ReferenceLibrary) { m_ReferenceObjects[referenceObject.guid] = referenceObject; } m_ReferenceObjectCount = m_ReferenceObjects.Count; } int m_ReferenceObjectCount; Dictionary m_ReferenceObjects = new Dictionary(); } }