Most Spatial Anchors functions are asynchronous. That is, the results of the functions can’t be processed immediately as part of the return value and instead the results are broadcast later. In a Blueprint, this is performed using latent actions. There are success and failure execution pins available for every asynchronous Spatial Anchors function. In code, this is performed with a callback delegate passed to the function call.
Call Asynchronous Blueprint Function
Using one of the latent Spatial Anchors actions, you can respond to success or failure events for an asynchronous call by connecting to the output execution pins. Keep in mind that the success and failure execution pins don’t execute in the same frame as the start of the function call. To execute logic that isn’t dependent on the asynchronous results of Spatial Anchors Blueprints you can continue the execution flow by way of the unnamed immediate execution pin.
After the asynchronous function is completed, the success or failure pins execute. If the request was successful you can use the output data members that are part of the latent action.
Call Asynchronous C++ Function
Executing an asynchronous function in C++ requires passing a delegate as a parameter to the function that starts the asynchronous work. This delegate is executed in the case of success or failure and has a parameter that determines success as well as other parameters you can use in the success case. For more information, see “Delegates” in the Unreal Engine documentation.
Each anchor that a user wants to re-use over multiple sessions must have the anchor’s UUID saved to the headset’s local storage. Anchors saved to the cloud are not persistent indefinitely. Anchors saved using SaveAnchor or SaveAnchorList can be saved to the headset or to the cloud. This storage is accessible to a user and can be queried by way of QueryAnchors. You can load a specific set of anchors by providing a list of anchor UUIDs to the function call.
For locally persistent spatial anchors we recommend you save spatial anchors to an app-specific, persistent save game, and query anchors by way of a list of saved UUIDs. For more information, see “Saving and Loading Your Game” in the Unreal Engine documentation.
Use the Blueprint Interface
There’s no need to add any mandatory components or managers to a scene to use spatial anchors. You can access the Spatial Anchors system from Blueprints and we provide a set of Blueprint nodes that you can use. For more information, see Blueprint API Reference.
Create Spatial Anchor Example
Spawn an actor.
This actor does not have to have a spatial anchor component attached.
Call the Blueprint method Oculus Async Create Spatial Anchor and pass in the anchor transform and actor as parameters.
If the specified actor does not have a spatial anchor component attached, a new component is constructed for you.
Execute logic using the Success and Failure pins.
The resulting Anchor component output is only valid in the case of success.
Erase Spatial Anchor Example
Call the Blueprint method Oculus Async Erase Anchor.
Pass in an actor that has a spatial anchor attached.
Execute logic using the Success or Failure pins.
The resulting Actor and UUID output is only valid in the case of success.
The UUID of the destroyed anchor is returned for your bookkeeping.
Erase can also work as an “unsave” operation. It is up to you to decide whether you destroy the anchor actor representation as part of Erase.
Note: Cloud saved spatial anchors cannot be erased from storage.
Save Spatial Anchor Example
You can save a specific spatial anchor or multiple anchors.
To save a specific spatial anchor:
Call the Blueprint method Oculus Async Save Anchor.
Specify the target actor that has a spatial anchor attached.
Specify the storage location, this is either local or cloud.
Execute logic using the Success or Failure pins.
The output Anchor Component is only valid if success is executed.
To save multiple anchors:
Call the Blueprint method Oculus Async Save Anchors.
Specify the target actors that have spatial anchors attached.
Specify the storage location, this is either Local or Cloud..
Execute logic using the Success or Failure pins.
The output Anchor Components array is only valid if success is executed.
Load Spatial Anchor Example
Get a list of Anchor UUIDs to request loading.
This can be from a save game or anywhere else you are storing UUIDs.
Call the Blueprint method Oculus Async Query Anchors.
Specify the location to save to, this can be local or cloud.
If successful, iterate the query results and then construct new actors using the Spawn Oculus Anchor Actor function.
Using the Spatial Anchors C++ API
The Spatial Anchors C++ API is accessed through the OculusAnchors header file. Each asynchronous function that is part of the interface takes a delegate parameter as the last argument to the function. This delegate has a boolean parameter as its first argument which represents the success or failure state of that call. The following table lists each delegate and their associated parameters.
Delegate
Parameters
FOculusSpatialAnchorCreateDelegate
EOculusResult::Type Result UOculusAnchorComponent* Anchor
FOculusAnchorEraseDelegate
EOculusResult::Type Result FUUID AnchorUUID
FOculusAnchorSaveDelegate
EOculusResult::Type Result UOculusAnchorComponent* Anchor
FOculusAnchorSaveListDelegate
bool Success const TArray<UOculusAnchorComponent*> and SavedAnchors
FOculusAnchorQueryDelegate
EOculusResult::Type Result const TArray<FOculusSpaceQueryResult> and Results
Note: The example code below makes use of lambda delegate bindings. This isn’t a requirement to use the API and is only used to shorten the code being shown.
Create Spatial Anchor Example
Spawn an actor.
This actor does not have to have a spatial anchor component attached.
Call the method OculusAnchors::CreateSpatialAnchor and pass the anchor transform, actor, and result delegate in as parameters.
If the specified actor does not have a spatial anchor component attached, a new component is constructed for you.
Execute logic in the results delegate.
The resulting spatial anchor component is only valid in the case of success.
AActor* NewActor = GetWorld()->SpawnActor<AActor>();
OculusAnchors::FOculusAnchors::CreateSpatialAnchor(NewActor->GetActorTransform(),
NewActor, FOculusSpatialAnchorCreateDelegate::CreateLambda([](bool Success,
UOculusAnchorComponent* AnchorComponent)
{
// Post-create logic in here
})
);
Erase Spatial Anchor Example
Retrieve an anchor from an actor.
Call the method OculusAnchors::EraseAnchor and pass the anchor component and result delegate in as parameters.
Execute logic in the results delegate.
The resulting UUID is only valid in the case of success.
Call the method OculusAnchors::QueryAnchors and pass the list of UUIDs, the query location, the maximum number of anchors to load, and the result delegate in as parameters.
Execute logic in the results delegate.
Spawn an actor of your choice, there is a helper method you can use called SpawnActorWithAnchorQueryResults.
We now expose error codes as the result of Spatial Anchors functions. These error codes are available as an output from the Blueprint API and the C++ API. Error codes are defined in the EOculusResult enum. Most enumeration results are general but there are specific enumerations available for spatial anchors.
Failure_SpaceCloudStorageDisabled: Saving anchors to cloud storage is not permitted by the user.
Failure_SpaceMappingInsufficient: The user did not move around enough for a reliable localization. The user should walk and look around their space before calling save again. For example, the user could walk in a large circle around the center of their playspace.
Failure_SpaceLocalizationFailed: The system failed to localize the shared anchor. This could be because the shared anchor is not near the user when calling Query.
The API for Spatial Anchors changed to an improved version in Oculus SDK v43. Any legacy versions of Spatial Anchors in existing projects need to be migrated to this current version.
In general, all legacy Spatial Anchors calls that relied on event listeners have now been changed to latent actions. This means you can fold the event logic into a single execution flow graph rather than relying on a bifurcated event response model.
For example, the legacy Spatial Anchors logic for creating a spatial anchor looked like the following diagram:
You would:
Bind a callback, usually in begin play, to the Spatial Anchors event you are listening for.
Execute a Spatial Anchors method, in this case “Create Spatial Anchor”.
Wait for the bound callback to execute.
Complete any work necessary in the callback.
In contrast, the current Spatial Anchors logic now resembles the following diagram:
Execute a latent action Blueprint nodes.
Execute Success of Failure pins based on results.
The following table lists the legacy Spatial Anchors calls and their new latent action names. For more information, see Spatial Anchors Blueprint Reference.
Binding
Latent Action
Create Spatial Anchor
Oculus Async Create Spatial Anchor
Erase Spatial Anchor
Oculus Async Erase Anchor
Save Spatial Anchor
Oculus Async Save Anchor
Query All Local Spatial Anchors
Oculus Async Query Anchors
You can use the SpatialAnchorsSample sample project as an example of how to use Spatial Anchors after migrating.