Introduction
AR Foundation provides a unified workflow for building cross-platform augmented reality apps in Unity. Instead of writing separate code for ARCore (Android) and ARKit (iOS), you build once using AR Foundation's abstraction layer. This guide covers the essentials of modern AR Foundation versions using
XROrigin, focusing on plane detection, robust object placement, and scene stability. Note that specific package or API details may vary slightly depending on your exact Unity and AR Foundation versions.AR Foundation Setup
To begin, you need the right packages and configuration:
- AR Foundation Package: Install this via the Unity Package Manager. It provides the core scripts and components.
- XR Plug-in Management: Also installed via the Package Manager, this acts as the loader for platform-specific AR providers.
- ARCore XR Plug-in / ARKit XR Plug-in: Install the ARCore plugin if you are targeting Android, and the ARKit plugin if you are targeting iOS. You must also enable them in Edit > Project Settings > XR Plug-in Management under their respective platform tabs.
- AR Foundation Package: Install this via the Unity Package Manager. It provides the core scripts and components.
- XR Plug-in Management: Also installed via the Package Manager, this acts as the loader for platform-specific AR providers.
- ARCore XR Plug-in / ARKit XR Plug-in: Install the ARCore plugin if you are targeting Android, and the ARKit plugin if you are targeting iOS. You must also enable them in Edit > Project Settings > XR Plug-in Management under their respective platform tabs.
Scene Hierarchy Setup
A typical AR scene requires a specific hierarchy of GameObjects to bridge the physical and digital worlds:
- AR Session: This component controls the lifecycle of the AR experience. It enables or disables tracking system-wide.
- XROrigin: The center of your tracking space. It transforms trackable features (like physical planes) into Unity world coordinates.
- Camera: Tagged as MainCamera, nested under the XROrigin, and equipped with an
- ARPlaneManager: Attached to the XROrigin, it generates and tracks flat surfaces (floors, walls, tables).
- ARRaycastManager: Attached to the XROrigin, it allows you to cast rays against the detected physical planes.
- ARAnchorManager (Optional): Attached to the XROrigin, it tracks specific points in space, ensuring placed objects remain firmly attached to the physical world.
- AR Session: This component controls the lifecycle of the AR experience. It enables or disables tracking system-wide.
- XROrigin: The center of your tracking space. It transforms trackable features (like physical planes) into Unity world coordinates.
- Camera: Tagged as MainCamera, nested under the XROrigin, and equipped with an
ARPoseDriver or TrackedPoseDriver to track the physical device's movement.- ARPlaneManager: Attached to the XROrigin, it generates and tracks flat surfaces (floors, walls, tables).
- ARRaycastManager: Attached to the XROrigin, it allows you to cast rays against the detected physical planes.
- ARAnchorManager (Optional): Attached to the XROrigin, it tracks specific points in space, ensuring placed objects remain firmly attached to the physical world.
Plane Detection
The
To help users understand what the camera sees, you should assign a Plane Prefab to the manager. Unity provides an
ARPlaneManager handles surface tracking. The supported and requested plane detection modes (e.g., horizontal floors or vertical walls) depend on the underlying provider and your configured detection mode. Modern AR Foundation uses requestedDetectionMode and currentDetectionMode APIs to manage this. You can restrict the detection via the manager's Detection Mode dropdown if your app only requires floor placement, though exact Inspector and API details can vary by package version.To help users understand what the camera sees, you should assign a Plane Prefab to the manager. Unity provides an
AR Default Plane as a sample/scene object that can be saved as a prefab and assigned to the ARPlaneManager. This overlays a grid or translucent color over detected surfaces, providing crucial visual feedback before the user taps the screen.Raycasting and Object Placement
Physical AR planes do not inherently have Unity physics colliders. To interact with them, you must use the
ARRaycastManager. A robust placement script should check that the user isn't tapping a UI element, use TrackableType.PlaneWithinPolygon for accurate surface hits, and manage a single placed object rather than blindly instantiating new objects on every tap.csharp
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR.ARFoundation;
using UnityEngine.XR.ARSubsystems;
using UnityEngine.EventSystems;
[RequireComponent(typeof(ARRaycastManager))]
public class ARPlacementManager : MonoBehaviour {
public GameObject prefabToPlace;
private GameObject _spawnedObject;
private ARRaycastManager _raycastManager;
private List<ARRaycastHit> _hits = new List<ARRaycastHit>();
void Awake() {
_raycastManager = GetComponent<ARRaycastManager>();
}
void Update() {
if (Input.touchCount == 0) return;
Touch touch = Input.GetTouch(0);
if (touch.phase != TouchPhase.Began) return;
// Sensible UI guard: don't place objects if tapping a UI button
if (EventSystem.current.IsPointerOverGameObject(touch.fingerId)) return;
if (_raycastManager.Raycast(touch.position, _hits, TrackableType.PlaneWithinPolygon)) {
Pose hitPose = _hits[0].pose;
if (_spawnedObject == null) {
_spawnedObject = Instantiate(prefabToPlace, hitPose.position, hitPose.rotation);
} else {
// Reposition the existing object instead of instantiating endlessly
_spawnedObject.transform.position = hitPose.position;
_spawnedObject.transform.rotation = hitPose.rotation;
}
}
}
}Keeping Objects Stable
AR Foundation continuously updates its understanding of the environment. As you move around, the system might shift or merge planes to correct its physical map. If an object is simply instantiated at a coordinate, it might appear to float or jump as the AR coordinate space adjusts.
Anchors provide a dedicated tracking reference when the application needs one. By creating an
Anchors provide a dedicated tracking reference when the application needs one. By creating an
ARAnchor at your hit location and parenting your object to it, you tell the AR system: "Keep this specific point locked to the physical world, no matter how you adjust the planes around it." While raw GameObjects don't necessarily drift in every situation (especially in highly-textured, well-lit rooms), anchors can provide a more stable tracked reference for long-lasting placement.Disabling Plane Detection After Placement
Detecting and rendering planes requires heavy continuous computer vision processing. Once your user has successfully placed their object, you can disable the
ARPlaneManager component (planeManager.enabled = false;) and hide the existing plane visuals. This can reduce ongoing processing and power usage, and creates a cleaner visual experience.Android and iOS Build Configuration
When building your project, ensure platform validation is met:
- XR Plug-in Management: Verify that ARCore (Android) or ARKit (iOS) is checked in your build settings.
- Camera Permissions & ARCore: Both platforms require explicit camera permissions. On iOS, you must set the Camera Usage Description in the Player Settings. On Android, ARCore automatically adds the camera permission to the manifest, but you must still handle runtime permission requests if you customize the startup flow. For AR Required or AR Optional apps, also handle ARCore availability and Google Play Services for AR installation at runtime using the AR Foundation session APIs, rather than assuming every supported device is ready to start an AR session.
- Minimum OS: Ensure your minimum Android API level is at least 24 (7.0) for ARCore, and iOS is at least 11.0.
- XR Plug-in Management: Verify that ARCore (Android) or ARKit (iOS) is checked in your build settings.
- Camera Permissions & ARCore: Both platforms require explicit camera permissions. On iOS, you must set the Camera Usage Description in the Player Settings. On Android, ARCore automatically adds the camera permission to the manifest, but you must still handle runtime permission requests if you customize the startup flow. For AR Required or AR Optional apps, also handle ARCore availability and Google Play Services for AR installation at runtime using the AR Foundation session APIs, rather than assuming every supported device is ready to start an AR session.
- Minimum OS: Ensure your minimum Android API level is at least 24 (7.0) for ARCore, and iOS is at least 11.0.
Performance Tips
- Limit Raycasts: Only raycast when the user actually taps the screen, not every frame.
- Manage Visualizers: Complex plane visualizers with heavy shaders can cause GPU bottlenecks. Use simple, unlit materials for plane grids.
- Target FPS: Frame-rate targets are device and project dependent. While 60 FPS is ideal for smooth tracking, 30 FPS is often safer for complex AR scenes to prevent the device from overheating and throttling the CPU.
- Manage Visualizers: Complex plane visualizers with heavy shaders can cause GPU bottlenecks. Use simple, unlit materials for plane grids.
- Target FPS: Frame-rate targets are device and project dependent. While 60 FPS is ideal for smooth tracking, 30 FPS is often safer for complex AR scenes to prevent the device from overheating and throttling the CPU.
Common Problems and Troubleshooting
- Black Camera Background: This usually means the
- No Planes Detected: Ensure you are testing on a physical device (the Unity Editor simulator is limited without specific mock setups). Also, AR requires well-lit environments and textured surfaces; plain white floors or dark rooms will fail to track.
- Object Appears in Wrong Location: Ensure your prefab's pivot point is at its base (the feet), not its center, otherwise it will spawn half-sunken into the floor.
- Permission/Setup Problems: Re-verify that XR Plug-in Management is configured and the platform-specific AR provider (ARCore/ARKit) is installed and enabled.
ARSession component is missing from the scene, the AR camera setup lacks an ARCameraManager and ARCameraBackground configured, or the app lacks camera permissions.- No Planes Detected: Ensure you are testing on a physical device (the Unity Editor simulator is limited without specific mock setups). Also, AR requires well-lit environments and textured surfaces; plain white floors or dark rooms will fail to track.
- Object Appears in Wrong Location: Ensure your prefab's pivot point is at its base (the feet), not its center, otherwise it will spawn half-sunken into the floor.
- Permission/Setup Problems: Re-verify that XR Plug-in Management is configured and the platform-specific AR provider (ARCore/ARKit) is installed and enabled.
Frequently Asked Questions
Can I detect horizontal and vertical planes together?
Yes, when the underlying AR provider supports both modes. Configure the requested detection mode accordingly.
Why is the AR camera black?
A black screen almost always indicates that the
Why are planes not appearing?
You may have forgotten to assign a plane prefab to the
Do I always need ARAnchorManager?
No. For quick, temporary placement or simple toys, placing objects relative to a plane without anchors might be perfectly acceptable. However, for precise, long-lasting placement that requires high stability, anchors are strongly recommended.
Yes, when the underlying AR provider supports both modes. Configure the requested detection mode accordingly.
Why is the AR camera black?
A black screen almost always indicates that the
ARSession is missing, XR Plug-in Management is not configured for the target platform, or the user denied camera permissions.Why are planes not appearing?
You may have forgotten to assign a plane prefab to the
ARPlaneManager, or you are testing in a poorly lit/featureless room. AR relies on visual contrast to track surfaces.Do I always need ARAnchorManager?
No. For quick, temporary placement or simple toys, placing objects relative to a plane without anchors might be perfectly acceptable. However, for precise, long-lasting placement that requires high stability, anchors are strongly recommended.
