using System; using System.Collections.Generic; using UnityEngine.Serialization; using UnityEngine.XR.ARSubsystems; namespace UnityEngine.XR.ARFoundation { /// /// Manages anchors. /// /// /// Use this component to programmatically add, remove, or query for /// anchors. Anchors are Poses in the world /// which will be periodically updated by an AR device as its understanding /// of the world changes. /// Subscribe to changes (added, updated, and removed) via the /// event. /// /// [DefaultExecutionOrder(ARUpdateOrder.k_AnchorManager)] [DisallowMultipleComponent] [RequireComponent(typeof(ARSessionOrigin))] [HelpURL("https://docs.unity3d.com/Packages/com.unity.xr.arfoundation@3.0/api/UnityEngine.XR.ARFoundation.ARAnchorManager.html")] public sealed class ARAnchorManager : ARTrackableManager< XRAnchorSubsystem, XRAnchorSubsystemDescriptor, XRAnchor, ARAnchor> { [SerializeField] [Tooltip("If not null, instantiates this prefab for each instantiated anchor.")] [FormerlySerializedAs("m_ReferencePointPrefab")] GameObject m_AnchorPrefab; /// /// Getter/setter for the Anchor Prefab. /// public GameObject anchorPrefab { get { return m_AnchorPrefab; } set { m_AnchorPrefab = value; } } /// /// Invoked once per frame to communicate changes to anchors, including /// new anchors, the update of existing anchors, and the removal /// of previously existing anchors. /// public event Action anchorsChanged; /// /// Attempts to add an with the given Pose. /// /// /// If /// is not null, a new instance of that prefab will be instantiated. Otherwise, a /// new GameObject will be created. In either case, the resulting /// GameObject will have an component on it. /// /// The pose, in Unity world space, of the . /// A new if successful, otherwise null. public ARAnchor AddAnchor(Pose pose) { if (!enabled) throw new InvalidOperationException("Cannot create a anchor from a disabled anchor manager."); if (subsystem == null) throw new InvalidOperationException("Anchor manager has no subsystem. Enable the manager first."); var sessionRelativePose = sessionOrigin.trackablesParent.InverseTransformPose(pose); // Add the anchor to the XRAnchorSubsystem XRAnchor sessionRelativeData; if (subsystem.TryAddAnchor(sessionRelativePose, out sessionRelativeData)) return CreateTrackableImmediate(sessionRelativeData); return null; } /// /// Attempts to create a new anchor that is attached to an existing . /// /// The to which to attach. /// The initial Pose, in Unity world space, of the anchor. /// A new if successful, otherwise null. public ARAnchor AttachAnchor(ARPlane plane, Pose pose) { if (!enabled) throw new InvalidOperationException("Cannot create a anchor from a disabled anchor manager."); if (subsystem == null) throw new InvalidOperationException("Anchor manager has no subsystem. Enable the manager first."); if (plane == null) throw new ArgumentNullException("plane"); var sessionRelativePose = sessionOrigin.trackablesParent.InverseTransformPose(pose); XRAnchor sessionRelativeData; if (subsystem.TryAttachAnchor(plane.trackableId, sessionRelativePose, out sessionRelativeData)) return CreateTrackableImmediate(sessionRelativeData); return null; } /// /// Attempts to remove an . /// /// The anchor you wish to remove. /// /// True if the anchor was successfully removed. /// False usually means the anchor is not longer tracked by the system. /// public bool RemoveAnchor(ARAnchor anchor) { if (!enabled) throw new InvalidOperationException("Cannot create a anchor from a disabled anchor manager."); if (subsystem == null) throw new InvalidOperationException("Anchor manager has no subsystem. Enable the manager first."); if (anchor == null) throw new ArgumentNullException("anchor"); if (subsystem.TryRemoveAnchor(anchor.trackableId)) { DestroyPendingTrackable(anchor.trackableId); return true; } return false; } /// /// Gets the with given , /// or null if it does not exist. /// /// The of the to retrieve. /// The with or null if it does not exist. public ARAnchor GetAnchor(TrackableId trackableId) { ARAnchor anchor; if (m_Trackables.TryGetValue(trackableId, out anchor)) return anchor; return null; } protected override GameObject GetPrefab() { return m_AnchorPrefab; } protected override string gameObjectName { get { return "Anchor"; } } protected override void OnTrackablesChanged( List addedPoints, List updatedPoints, List removedPoints) { if (anchorsChanged != null) { anchorsChanged( new ARAnchorsChangedEventArgs( addedPoints, updatedPoints, removedPoints)); } } } }