using System; using System.Collections.Generic; using UnityEngine.XR.ARSubsystems; using Unity.XR.CoreUtils; using UnityEngine.Serialization; namespace UnityEngine.XR.ARFoundation { /// /// Creates, updates, and removes GameObjects with components under the /// 's . /// /// /// When enabled, this component subscribes to event to update face data. /// If this component is disabled, and there are no other subscribers to those events, /// face detection will be disabled on the device. /// /// Related information: AR Face Manager component /// [RequireComponent(typeof(XROrigin))] [DisallowMultipleComponent] [DefaultExecutionOrder(ARUpdateOrder.k_FaceManager)] [AddComponentMenu("XR/AR Foundation/AR Face Manager")] [HelpURL("features/face-tracking")] public sealed class ARFaceManager : ARTrackableManager< XRFaceSubsystem, XRFaceSubsystemDescriptor, XRFaceSubsystem.Provider, XRFace, ARFace> { [SerializeField] [Tooltip("If not null, instantiates this prefab for each created face.")] GameObject m_FacePrefab; /// /// Getter/setter for the Face Prefab. /// public GameObject facePrefab { get => m_FacePrefab; set => m_FacePrefab = value; } [SerializeField] [Tooltip("The maximum number of faces to track simultaneously.")] int m_MaximumFaceCount = 1; /// /// Get or set the requested maximum number of faces to track simultaneously /// public int requestedMaximumFaceCount { get => subsystem?.requestedMaximumFaceCount ?? m_MaximumFaceCount; set { m_MaximumFaceCount = value; if (enabled && subsystem != null) { subsystem.requestedMaximumFaceCount = value; } } } /// /// Get the maximum number of faces to track simultaneously. /// public int currentMaximumFaceCount => subsystem?.currentMaximumFaceCount ?? 0; /// /// Get the supported number of faces that can be tracked simultaneously. This value /// might change when the configuration changes. /// public int supportedFaceCount => subsystem?.supportedFaceCount ?? 0; /// /// Raised for each new detected in the environment. /// [Obsolete("facesChanged has been deprecated in AR Foundation version 6.0. Use trackablesChanged instead.", false)] public event Action facesChanged; /// /// Attempts to retrieve an . /// /// The TrackableId associated with the . /// The if found. null otherwise. public ARFace TryGetFace(TrackableId faceId) { m_Trackables.TryGetValue(faceId, out ARFace face); return face; } /// /// Invoked just before calling `Start` on the Subsystem. Used to set the `requestedMaximumFaceCount` /// on the subsystem. /// protected override void OnBeforeStart() { subsystem.requestedMaximumFaceCount = m_MaximumFaceCount; } /// /// Invoked just after an has been updated. /// /// /// protected override void OnAfterSetSessionRelativeData( ARFace face, XRFace sessionRelativeData) { face.UpdateMesh(subsystem); if (subsystem.subsystemDescriptor.supportsEyeTracking) face.UpdateEyes(); } /// /// Invoked when the base class detects trackable changes. /// /// The list of added s. /// The list of updated s. /// The list of removed s. [Obsolete("OnTrackablesChanged() has been deprecated in AR Foundation version 6.0.", false)] protected override void OnTrackablesChanged( List added, List updated, List removed) { if (facesChanged != null) { using (new ScopedProfiler("OnFacesChanged")) facesChanged?.Invoke(new ARFacesChangedEventArgs(added, updated, removed)); } } /// /// Get the Prefab that will be instantiated for each . Can be `null`. /// /// The prefab that will be instantiated for each . protected override GameObject GetPrefab() => m_FacePrefab; /// /// The name assigned to each `GameObject` belonging to each . /// protected override string gameObjectName => "ARFace"; } }