Subsystems
A subsystem (shorthand for SubsystemWithProvider) defines the life cycle and scripting interface of a Unity engine feature. All subsystems share a common subsystem life cycle, but their feature implementations can vary on different platforms, providing a layer of abstraction between your application code and platform-specific SDK's such as Google ARCore or Apple ARKit.
AR Foundation defines its AR features using subsystems. For example, the XRPlaneSubsystem defines an interface for plane detection. You use the same application code to interact with a detected plane on iOS and Android — or any other platform with an implementation of the plane subsystem — but AR Foundation itself does not contain subsystem implementations for these platforms.
Subsystem implementations are called providers, and are typically made available in separate packages called provider plug-ins. For example, the Google ARCore XR Plug-in provides subsystem implementations for the Android platform, and the Apple ARKit XR Plug-in provides implementations for iOS.
With the exception of Device tracking, the table below lists AR Foundation's AR features and their corresponding subsystems. (Device tracking uses the Input System and is not subsytem-based.)
Subsystem life cycle
All subsystems have the same life cycle: they can be created, started, stopped, and destroyed. You don't typically need to create or destroy a subsystem instance yourself, as this is the responsibility of Unity's active XRLoader
. Each provider plug-in contains an XRLoader
implementation (or simply, a loader). Most commonly, a loader creates an instance of all applicable subsystems when your application initializes and destroys them when your application quits, although this behavior is configurable. When a trackable manager goes to Start
a subsystem, it gets the subsystem instance from the project's active loader based on the settings found in Project Settings > XR Plug-in Management. For more information about loaders and their configuration, see the XR Plug-in Management end-user documentation.
In a typical AR Foundation scene, any managers present in the scene will Start
and Stop
their subsystems when the manager is enabled or disabled, respectively. The exact behavior of Start
and Stop
varies by subsystem, but generally corresponds to "start doing work" and "stop doing work", respectively. You can start or stop a subystem at any time based on the needs of your application.
Subsystem descriptors
Each subsystem has a corresponding SubsystemDescriptor whose properties describe the range of the subystem's capabilities. Providers might assign different values to these properties at runtime based on different platform or device limitations.
Wherever you use a capability described in a subsystem descriptor, you should check its property value at runtime first to confirm whether that capability is supported on the target device, as shown in the example below:
var trackedImageManager = FindObjectOfType(typeof(ARTrackedImageManager));
var imageTrackingSubystem = trackedImageManager.subsystem;
// Query whether the image tracking provider supports runtime modification
// of reference image libraries
if (imageTrackingSubsystem.subsystemDescriptor.supportsMutableLibrary)
{
// take some action
}
// Equivalently:
if (trackedImageManager.descriptor.supportsMutableLibrary)
{
// take some action
}
Tracking subsystems
A tracking subsystem is a subsystem that detects and tracks one or more objects, called trackables, in the physical environment.
A trackable represents something that a tracking subsystem can detect and track. For example, the XRPlaneSubsystem detects and tracks BoundedPlane trackables. Each trackable has a TrackableId
, which is a 128-bit GUID (Globally Unique Identifier) that can be used to uniquely identify trackables across multiple frames as they are added, updated, or removed.
In code, a trackable is defined as any class which implements ITrackable. In the UnityEngine.XR.ARSubsystems
namespace, all trackable implementations (like BoundedPlane) are structs. In the UnityEngine.XR.ARFoundation
namespace, all trackable implementations (like ARPlane) are components which wrap these structs.