Have persistence across multiple Unity scenes using spatial anchors

Have persistence across multiple Unity scenes using spatial anchors

One of the challenges when building HoloLens applications is handling the persistence of holograms. Persistence of holograms allows us to store and share real world coordinates of holograms. This is useful when you restart you application and wants to have holograms appear at the same location where you left them. Persistence is also used when you want to share across multiple HoloLens devices to create a sharing experience which allows all the users see holograms at the same position in the room.

Spatial anchors

To have persistence of holograms in your scene, you have something called spatial anchors. A spatial anchor allows us to have to most accurate positioning for holograms. It also helps to to translate between the HoloLens coordinates and the real-world coordinates. In combination with the spatial anchor store you are able to share these coordinates between instances of the application and even over multiple devices. Adding a spatial anchor is nothing more than adding a component called WorldAnchor. You do not have to worry about performance since WorldAnchor is very cheap. But as soon as a WorldAnchor is set it is not allowed anymore to move the hologram. When you need to move the hologram, you will need to remove the WorldAnchor before the move and add it after again.

Share across multiple scenes

When you use multiple scenes in your Unity project each containing a separate camera you will notice that activating a new scene will actually restart the HoloLens at a new location. The position and rotation of the camera will be different from the previous scene. Sharing holograms across these scenes by using only their coordinates will cause holograms to appear at different locations depending on the start point of the camera in that scene. Could persistence helps us out?

Implementation

Indeed it can! Persistence also allows us also to maintain hologram positions across scenes. I wrote a small class which you can cooperate in your project.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.VR.WSA.Persistence;

public delegate void StoreLoaded();
public class GlobalStorage
{
    private WorldAnchorStore store = null;

    private static GlobalStorage instance = null;

    public event StoreLoaded OnStoreLoaded;

    protected GlobalStorage()
    {
        WorldAnchorStore.GetAsync(AnchorStoreReady);
    }

    public static GlobalStorage Instance
    {
        get
        {
            if (instance == null)
            {
                instance = new GlobalStorage();
            }

            return instance;
        }
    }

    public WorldAnchorStore Store
    {
        get
        {
            return store;
        }
    }

    public void AnchorStoreReady(WorldAnchorStore store)
    {
        this.store = store;

        if (OnStoreLoaded != null)
        {
            OnStoreLoaded();
        }
    }
}

We use a singleton pattern for the class GlobalStorage. An instance of such a class will reside across scenes. This allows us to have certain values stored which will be available in all scenes. Think of the last state we are in. In this class we use the spatial anchor store class named WorldAnchorStore. The problem with WorldAnchorStore is that you need to get asynchronous an instance of the class. Before you can use the store we need to be sure that it is loaded and ready. That means that any code depending on storing or retrieving world anchors needs to know when it is ready. As soon as an instance of GlobalStorage is created an instance of WorldAnchorStore is requested. When it is loaded the method AnchorStoreReady is called which stores the spatial anchor store as a property.

The GlobalStorage class also provides an event called OnStoreLoaded which is called when the store is ready. By subscribing to that event your code knows when it is able to store and retrieve world anchors.

Now you are able to store and retrieve hologram positions across scenes.

Conclusion

By using a “global” class as GlobalStorage we can maintain properties and values across the scenes. The spatial anchor store allows us to maintain hologram positions during restarting your application and sharing experiences across multiple devices. But is also allows us to store positions of holograms across multiple scenes in your HoloLens application.

This Post Has 2 Comments

  1. Martina

    Thanks Alexander, I was thinking about persistence and anchoring in relation to ARCloud design. Look forward to trying this out.

    1. Alexander Meijers

      Your welcome!

Leave a Reply