By default, World Locking Tools will restore Unity's coordinate system relative to the physical world across sessions. This means that to have a hologram appear the same place in the physical world after quitting and re-running the application, the hologram only needs to have the same Pose again.
If the application needs finer control, Auto-Save and Auto-Load may be disabled in the inspector, and persistence managed from a script as described in the persistence section of the documentation.
An additional API called the XRAnchorStore enables anchors to be persisted between sessions. The XRAnchorStore is a representation of the saved anchors on a device. Anchors can be persisted from ARAnchors in the Unity scene, loaded from storage into new ARAnchors, or deleted from storage.
Note
These anchors are to be saved and loaded on the same device. Cross-device anchor storage will be supported through Azure Spatial Anchors in a future release.
public class Microsoft.MixedReality.ARSubsystems.XRAnchorStore
{
// A list of all persisted anchors, which can be loaded.
public IReadOnlyList<string> PersistedAnchorNames { get; }
// Clear all persisted anchors
public void Clear();
// Load a single persisted anchor by name. The ARAnchorManager will create this new anchor and report it in
// the ARAnchorManager.anchorsChanged event. The TrackableId returned here is the same TrackableId the
// ARAnchor will have when it is instantiated.
public TrackableId LoadAnchor(string name);
// Attempts to persist an existing ARAnchor with the given TrackableId to the local store. Returns true if
// the storage is successful, false otherwise.
public bool TryPersistAnchor(string name, TrackableId trackableId);
// Removes a single persisted anchor from the anchor store. This will not affect any ARAnchors in the Unity
// scene, only the anchors in storage.
public void UnpersistAnchor(string name);
}
To load the XRAnchorStore, the plugin provides an extension method on the XRAnchorSubsystem, the subsystem of an ARAnchorManager:
public static Task<XRAnchorStore> LoadAnchorStoreAsync(this XRAnchorSubsystem anchorSubsystem)
To use this extension method, access it from an ARAnchorManager's subsystem as follows:
ARAnchorManager arAnchorManager = GetComponent<ARAnchorManager>();
XRAnchorStore anchorStore = await arAnchorManager.subsystem.LoadAnchorStoreAsync();
To see a full example of persisting / unpersisting anchors, check out the Anchors -> Anchors Sample GameObject and AnchorsSample.cs script in the Mixed Reality OpenXR Plugin Sample Scene:
An API called the XRAnchorStore enables anchors to be persisted between sessions. The XRAnchorStore is a representation of the saved anchors on a device. Anchors can be persisted from ARAnchors in the Unity scene, loaded from storage into new ARAnchors, or deleted from storage.
Note
These anchors are to be saved and loaded on the same device. Cross-device anchor storage will be supported through Azure Spatial Anchors in a future release.
public class UnityEngine.XR.WindowsMR.XRAnchorStore
{
// A list of all persisted anchors, which can be loaded.
public IReadOnlyList<string> PersistedAnchorNames { get; }
// Clear all persisted anchors
public void Clear();
// Load a single persisted anchor by name. The ARAnchorManager will create this new anchor and report it in
// the ARAnchorManager.anchorsChanged event. The TrackableId returned here is the same TrackableId the
// ARAnchor will have when it is instantiated.
public TrackableId LoadAnchor(string name);
// Attempts to persist an existing ARAnchor with the given TrackableId to the local store. Returns true if
// the storage is successful, false otherwise.
public bool TryPersistAnchor(TrackableId id, string name);
// Removes a single persisted anchor from the anchor store. This will not affect any ARAnchors in the Unity
// scene, only the anchors in storage.
public void UnpersistAnchor(string name);
}
To load the XRAnchorStore, the plugin provides an extension method on the XRReferencePointSubsystem (Unity 2019) or XRAnchorSubsystem (Unity 2020), the subsystem of an ARReferencePointManager/ARAnchorManager:
public static Task<XRAnchorStore> TryGetAnchorStoreAsync(this XRReferencePointSubsystem anchorSubsystem); // Unity 2019
public static Task<XRAnchorStore> TryGetAnchorStoreAsync(this XRAnchorSubsystem anchorSubsystem); // Unity 2020
To use this extension method, access it from an ARAnchorManager's subsystem as follows for Unity 2019:
ARReferencePointManager arReferencePointManager = GetComponent<ARReferencePointManager>();
XRAnchorStore anchorStore = await arReferencePointManager.subsystem.TryGetAnchorStoreAsync();
or for Unity 2020:
ARAnchorManager arAnchorManager = GetComponent<ARAnchorManager>();
XRAnchorStore anchorStore = await arAnchorManager.subsystem.TryGetAnchorStoreAsync();
The WorldAnchorStore is the key to creating holographic experiences where holograms stay in specific real world positions across instances of the application. Users can then pin individual holograms wherever they want, and find them later in the same spot over many uses of your app.
Namespace: UnityEngine.XR.WSA.Persistence
Class: WorldAnchorStore
The WorldAnchorStore will allow you to persist the location of WorldAnchor's across sessions. To actually persist holograms across sessions, you'll need to separately keep track of your GameObjects that use a particular world anchor. It often makes sense to create a GameObject root with a world anchor and have children holograms anchored by it with a local position offset.
To load holograms from previous sessions:
- Get the WorldAnchorStore
- Load app data relating to the world anchor, which gives you the ID of the world anchor
- Load a world anchor from its ID
To save holograms for future sessions:
- Get the WorldAnchorStore
- Save a world anchor specifying an ID
- Save app data relating to the world anchor along with an ID
You'll want to keep a reference to the WorldAnchorStore so you know when it's ready to perform an operation. Since this is an async call, potentially as soon as start up, you want to call:
WorldAnchorStore.GetAsync(StoreLoaded);
StoreLoaded in this case is our handler for when the WorldAnchorStore has completed loading:
private void StoreLoaded(WorldAnchorStore store)
{
this.store = store;
}
We now have a reference to the WorldAnchorStore, which we'll use to save and load specific World Anchors.
To save, we simply need to name what we are saving and pass it in the WorldAnchor we got before when we want to save. Note: trying to save two anchors to the same string will fail (store.Save will return false). Delete the previous save before saving the new one:
private void SaveGame()
{
// Save data about holograms positioned by this world anchor
if (!this.savedRoot) // Only Save the root once
{
this.savedRoot = this.store.Save("rootGameObject", anchor);
Assert(this.savedRoot);
}
}
And to load:
private void LoadGame()
{
// Save data about holograms positioned by this world anchor
this.savedRoot = this.store.Load("rootGameObject", rootGameObject);
if (!this.savedRoot)
{
s// We didn't actually have the game root saved! We have to re-place our objects or start over
}
}
We additionally can use store.Delete() to remove an anchor we previously saved and store.Clear() to remove all previously saved data.
To discover previously stored anchors, call GetAllIds.
string[] ids = this.store.GetAllIds();
for (int index = 0; index < ids.Length; index++)
{
Debug.Log(ids[index]);
}
You can use Azure Spatial Anchors to create a durable cloud anchor from a local WorldAnchor, which your app can then locate across multiple HoloLens, iOS and Android devices, even if those devices aren't present together at the same time. Because cloud anchors are persistent, multiple devices over time can each see content rendered relative to that anchor in the same physical location.
To get started building shared experiences in Unity, try out the 5-minute Azure Spatial Anchors Unity quickstarts.
Once you're up and running with Azure Spatial Anchors, you can then create and locate anchors in Unity.