# Anchor Sample

This sample demonstrates how to create and destroy local and saved anchors to accurately track a point in the real world. Please refer to the Unreal Engine documentation for basic information about anchors and what Unreal Engine's ARPin does (opens new window) and ARPin Local Storage (opens new window) works. In order to use this feature, it has to be enabled in the OpenXR plugin settings located under Project Settings > Snapdragon Spaces plugin.

# How the sample works

By default, when the sample is opened, a white gizmo appears 1 meter in front of the camera, but if a hit is detected in front of the camera, the gizmo will be yellow and will be placed at the hit location. In this sample, the user has two ways to place the gizmo in the current position: by tapping select on the controller or by using the Create button that appears in a floating UI when the gaze controller is enabled.

When the gizmo is placed, a simple white gizmo will appear to indicate that it is not an ARPin and also not tracked as such. A red, green and blue gizmo will appear once the underlying feature reports a tracked anchor. This will also attach an ARPin to the object. If the tracked gizmo is not tracking anymore or the creation of the ARPin fails, it'll be colored red. If the anchor is saved into the local anchor store, a cube mesh component will be displayed in the center of the gizmo.

The options available for the user in this sample are:

  • Destroy all anchors: A button to delete all the local gizmos placed in the world. This action don't destroy the saved anchors in the store.
  • Load all saved anchors: A button to load all the saved anchors and display them as local gizmos placed in the world.
  • Clear store: A button to remove all the saved anchors from the store. This action don't clear the local gizmos placed in the world.
  • Save created anchor to local store: A checkbox to save the local gizmos as saved anchors while creating.
Anchor sample UI panel

# Anchor Manager

The BP_AnchorManager blueprint (located under SnapdragonSpacesSamples Content > SnapdragonSpaces > Samples > Anchor > Placeable) centralizes the actions of creating and destroying gizmos. This blueprint binds the event from the pawn to interact with the sample (in this case, the tap select on the controller).

To enable and disable spatial anchors, the Toggle Spaces Feature method must be used with Spatial Anchor as the feature.

Also, in BP_Pawn a SceneComponent is added as root component for the unplaced gizmo. Some options that the developer can customize for the unplaced gizmo are:

  • AnchorTag: Name of the tag defines into the SceneComponent in BP_Pawn used as root for unplaced gizmo.
  • DistanceGizmo: Distance of the unplaced gizmo in front of the camera.

To place the gizmo, the manager detaches the gizmo from the root and uses his transform to create the ARPin gizmo.

Additionally, you can learn how to combine the anchor implementation with hit testing in the Update Hit function.

# Gizmo

The BP_Gizmo blueprint file (located under SnapdragonSpacesSamples Content > SnapdragonSpaces > Samples > Anchor > Placeable) is in charge of creating the ARPin. The PinComponent (opens new window) node is used to do this as seen in the image below.


For SnapdragonSpaces plug-in, it is mandatory to add the component that should be pinned (Component to Pin) and a transform where the component should be pinned (Pin to World Transform), if one of these inputs is empty, the ARPin creation fails.

Pin Component node

If the gizmo has the bAutoSave variable enabled, anchors are saved in the Anchor Store after the ARPin is assigned. Anchor saving happens in an asynchronous thread. The delegate OnSpacesAnchorIsSavedInfoResult indicates if saving was successful. The call can return the following results:

  • Success: Anchor saved in the store.
  • Generic Failure: Anchor not saved due to an OpenXR failure.
  • Insufficient Quality Failure: Anchor not saved due to failure of insufficient quality of the environment.
  • Anchor Not Created: Anchor not saved due to creation not yet completed.
  • Anchor Store Failure: Anchor not saved due to invalid anchor store.
  • Anchor Invalid: Anchor not saved due to invalid anchor value.
  • Anchor Destroyed: Anchor not saved due to its pending destruction.

The management of the Pin status is processed at the tick of this blueprint.

Finally, when the gizmo is being destroyed and has a valid ARPin, it removes the Pin manually.

# Loading and Saving Anchors


Make sure to look around your environment in order to generate a better tracking map and reduce saving and loading times. Saving multiple anchors at once blocks the main thread, so the callback should be used to save any subsequent anchor.

The OpenXR interface provides us the functions for loading and saving ARPins to a local store, using the Snapdragon Spaces plugin, the implementation of these happens in an asynchronous thread to avoid freezing issues in the application. For this reason, the developer has to consider that:

  • Load ARPins from Local Store

    • Loading all ARPins from local save. This node returns us a map of names and ARPins. These ARPins aren't loaded yet and their state will be Not Tracked until the asynchronous thread has finished loading all ARPins from the local store. When it is completed, the status of the ARPins will change automatically.

    Load ARPins from Local Store blueprint node

  • Save ARPin to Local Store

    • Saving an ARPin to a local store. This node saves an ARPin using a name as ID (it will be returned by the load nodes), the developer should use the On Spaces Anchor Is Saved delegate to know when the saving is completed successfully or not.

    On Spaces Anchor Is Saved delegate and Save ARPin to Local Store node

The Snapdragon Spaces plugin provides additional functions to help manage saved anchors from blueprints:

  • Get saved anchor names
    • Returns all anchor names saved in the store.
  • Get saved anchor names for ARPin
    • Returns the name used to save in the store for the ARPin.

Additional local anchor blueprint functions