Using Wayspot Anchors

Use VPS Wayspot Anchors to place virtual objects that maintain a consistent, stable pose in an AR environment. Wayspot Anchors allow you to precisely locate your AR content in the real world relative to a VPS-activated Wayspot or Private VPS Location. Wayspot Anchors can also be restored in future VPS sessions and shared between users of your app. Because Wayspot Anchors use position and orientation information relative to a VPS-activated Wayspot, you can set placement position with a much higher level of precision than just using GPS location.

Use Wayspot Anchors for scenarios where you need to place and share virtual content associated with VPS-activated Wayspots. Example scenarios include:

  • Place and find: Allow a user to place and persist virtual content near a VPS-activated Wayspot. At a future time, allow the user, or other users, to locate the object in the real world at the same location where it was placed using VPS.

  • Object discovery: You, or users of your app, can place virtual objects in the real world near VPS-activated Wayspots. Later, other users can discover these objects as they travel near the same real world locations.

  • Shared object interaction: Users collaborate at the same time with shared virtual objects when located together at the same VPS-activated Wayspot.

Note

VPS Wayspot Anchors should not be confused with ARDK AR anchors such as ARPlaneAnchor and ARImageAnchor. IARAnchor is not compatible with VPS Wayspot Anchors.

You can place a Wayspot Anchor once your app has:

  1. Obtained camera and location service permissions.

  2. Started a VPS session.

  3. Localized with a VPS-activated Wayspot.

Then you can use the Wayspot Anchor API to place Wayspot Anchors relative to the VPS-activated Wayspot the user has localized with.

The VPS Wayspot Anchor API provides two interfaces. WayspotAnchorService is a straight-forward “high-level” API for creating and managing Wayspot Anchors, whereas WayspotAnchorController is a “low-level” API that you can use if you need more granular control. In your app you can use WayspotAnchorService or WayspotAnchorController but not both. WayspotAnchorService creates and uses its own instance of WayspotAnchorController.

Note

Use of features such as VPS localization or the VPS Wayspot Anchors API involves the collection of personal information from your end user. For more information, see the Lightship ARDK Data Privacy FAQ.

Basic Flow

You can use the Wayspot Anchor API to create and place new Wayspot Anchors, or restore previously placed Wayspot Anchors. You can mix creating and restoring Anchors in your VPS session as needed. The basic flow for creating new Anchors is:

  1. Create and place a new Wayspot Anchor

  2. VPS Wayspots Anchor API returns a payload that you can persist for future restoring or sharing

  3. Use Anchors for placing GameObjects as needed

  4. Get Anchor tracking updates from the Wayspots Anchor API and use Anchor position updates to adjust GameObjects as needed

    Create and place a Wayspot Anchor

The basic flow for restoring Wayspot Anchors is similar, except you use your persisted payload information to restore the Anchors:

Restoring a Waypoint Anchor

Using WayspotAnchorService

WayspotAnchorService simplifies the process of localizing with VPS-activated Wayspots and working with Wayspot Anchors. WayspotAnchorService maintains a cache of Wayspot Anchors for you, and handles many of the low-level VPS events for you.

For an example of using WayspotAnchorService, see the WayspotAnchors sample in ARDK-examples. Many of the following code examples are from WayspotAnchorExampleManager in that sample.

Creating a Wayspot Anchor

To create a wayspot anchor, in your session where you’ve started VPS, call WayspotAnchorService.CreateWayspotAnchors() with your anchor positions and orientations in your local coordinate space. The current localization state must be LocalizationState.Localized before you create any anchors.

using Niantic.ARDK.AR.WayspotAnchors;

private void PlaceAnchor(Matrix4x4 localPose)
{
  var anchors = _wayspotAnchorService.CreateWayspotAnchors(localPose);
  if (anchors.Length == 0)
    return; // error raised in CreateWayspotAnchors

  // Cache IWayspotAnchors as needed, subscribe to anchor status and
  // tracking events. You can use WayspotAnchorTracker to handle some
  // of this automatically.
  // ...
}

WayspotAnchorService.CreateWayspotAnchors() returns immediately with a list of IWayspotAnchors, or an empty list if there was an issue with call to CreateWayspotAnchors() (for example, the localization state was not Localized).

The returned IWayspotAnchors will have an anchor ID that VPS assigns, that you’ll use to identify anchors during status or tracking events. The anchors will initially have a IWayspotAnchor.Status of WayspotAnchorStatusCode.Pending, indicating that VPS is in the process of creating the anchors.

You’ll need to track the created anchor status by registering a handler for each anchor’s IWayspotAnchor.StatusCodeUpdated event. If the status changes to Failed, the anchor could not be created and you won’t be able to use the anchor for placing game objects or tracking anchor position changes. To map StatusCodeUpdated events to IWayspotAnchors, either use the WayspotAnchorStatusUpdate.ID passed to the event handler, or create a class similar to WayspotAnchorTracker that gets associated with a IWayspotAnchor and adds its own StatusCodeUpdated event handler.

Each successfully created IWayspotAnchor will have a Payload, a binary blob that you should save to use when you want to restore previously created anchors, or to share the anchor with other users. The payload is created by VPS and is only available once the IWayspotAnchor.Status is WayspotAnchorStatusCode.Success or WayspotAnchorStatusCode.Limited. See Persisting and Sharing Wayspot Anchors for how to serialize and deserialize anchor payloads.

Once a Wayspot Anchor has been successfully created, you’ll need to subscribe to the anchor’s TransformUpdated event to get corrections from VPS for the anchor’s position and orientation as the user moves. See Handle Anchor Tracking Updates for how to do this.

Restoring a Wayspot Anchor

To restore a Wayspot Anchor created in a prior VPS session, use WayspotAnchorService.RestoreWayspotAnchors(). You’ll provide a list of anchor payloads that contain all the information needed to restore the anchors relative to the VPS-activated Wayspot where they were placed:

using Niantic.ARDK.AR.WayspotAnchors;

// Deserialize/load saved payloads, using WayspotAnchorPayload.Deserialize() as needed
// var payloads = ...load payloads...
if (payloads.Length > 0)
{
    var wayspotAnchors = _wayspotAnchorService.RestoreWayspotAnchors(payloads);

    // Cache IWayspotAnchors as needed, subscribe to anchor status and
    // tracking events. You can use WayspotAnchorTracker to handle some
    // of this automatically.
    // ...
}

If you need to load previously persisted Wayspot Anchor payloads see Persisting and Sharing Wayspot Anchors for how to serialize and deserialize Wayspot Anchors.

RestoreWayspotAnchors() returns an array of IWayspotAnchors similar to what CreateWayspotAnchors() returns.

You’ll need to track the restored anchor status by registering a handler for each anchor’s IWayspotAnchor.StatusCodeUpdated event. If the status changes to Failed, the anchor could not be restored and you won’t be able to use the anchor for placing game objects or tracking anchor position changes. To map StatusCodeUpdated events to IWayspotAnchors, either use the WayspotAnchorStatusUpdate.ID passed to the event handler, or create a class similar to WayspotAnchorTracker that gets associated with a IWayspotAnchor and adds its own StatusCodeUpdated event handler.

Just like when creating new anchors, you’ll need to subscribe to the anchor’s TransformUpdated event to get corrections from VPS for the anchor’s position and orientation as the user moves. See Handle Anchor Tracking Updates for how to do this.

Note

Restored anchors may not be fully resolved when RestoreWayspotAnchors() returns. If you’re not using WayspotAnchorTracker you should listen for TransformUpdated events for an anchor before assuming the anchor has been correctly placed in the world.

Deleting Wayspot Anchors

WayspotAnchorService manages a cache of Wayspot Anchors for you. If you no longer need to track one or more Wayspot Anchors, you can delete the Anchors from the cache using WayspotAnchorService.DestroyWayspotAnchors(), providing either a list of IWayspotAnchors or a list of anchor IDs.

using Niantic.ARDK.AR.WayspotAnchors;

Guid[] ids;

// ...populate ID array with Anchor IDs you want to remove...

// Delete anchors from cache using Anchor IDs
_wayspotAnchorService.DestroyWayspotAnchors(ids);

Restarting a VPS Session

If your app needs to restart the VPS session from scratch, you can use WayspotAnchorService.Restart(). See “Understanding Localization Flow” in Localizing with VPS for examples of when you might need to restart VPS. Also, see “Restarting VPS” in Localizing with VPS for additional details on what happens when you restart a VPS session.

Using WayspotAnchorController (For Advanced Users)

WayspotAnchorController provides a low-level interface for working with Wayspot Anchors. Use WayspotAnchorController if you need more flexibility, for example if you need to maintain your own cache of Wayspot Anchors.

For an example of using WayspotAnchorController, see the implementation of WayspotAnchorService in the ARDK source code in Assets/ARDK/AR/WayspotAnchors/WayspotAnchorService.cs.

For an example of creating a WayspotAnchorController instance, see “Using WayspotAnchorController” in Localizing with VPS.

Creating a Wayspot Anchor with WayspotAnchorController

First, set an event handler for WayspotAnchorController.WayspotAnchorsCreated wherever you create your WayspotAnchorController instance.

wayspotAnchorController.WayspotAnchorsCreated += HandleWayspotAnchorsCreated;

To create a Wayspot Anchor call WayspotAnchorController.CreateWayspotAnchors() with a list of anchor positions and orientations. The current localization state must be LocalizationState.Localized before you create any anchors. The call will make a request to the VPS backend and return an array of IDs of the anchors that VPS will create. WayspotAnchorController will send a WayspotAnchorsCreated event once all of the Anchors are created by VPS.

using Niantic.ARDK.AR.WayspotAnchors;

private readonly Dictionary<Guid, IWayspotAnchor> _wayspotAnchors;

private void PlaceWayspotAnchors(params Matrix4x4[] localPoses)
{
    // Set WayspotAnchorsCreated event handler here or in
    // your initialization code
    _wayspotAnchorController.WayspotAnchorsCreated += HandleWayspotAnchorsCreated;

    // ...Verified we've localized with a VPS-activated Wayspot, the most recent WayspotAnchorController.LocalizationStateUpdated event should indicate LocalizationState.Localized...

    var ids = _wayspotAnchorController.CreateWayspotAnchors(localPoses);

    // ...cache IDs to verify status in our HandleWayspotAnchorsCreated handler...
}

private void HandleWayspotAnchorsCreated(WayspotAnchorsCreatedArgs wayspotAnchorsCreatedArgs)
{
    var wayspotAnchors = wayspotAnchorsCreatedArgs.WayspotAnchors;
    foreach (var wayspotAnchor in wayspotAnchors)
    {
        // Look up anchor.ID in our cache, add associated IWayspotAnchor
        if (!_wayspotAnchors.ContainsKey(wayspotAnchor.ID))
        {
            // Check if VPS couldn't create the anchor
            if (wayspotAnchor.Status == WayspotAnchorStatusCode.Failed) {
                // ...handle failed anchor creation condition...
                continue;
            }
            _wayspotAnchors.Add(wayspotAnchor.ID, wayspotAnchor);
        }
        Debug.Log($"Created wayspot anchor {wayspotAnchor.ID}");
    }

    // Start tracking created anchors
    _wayspotAnchorController.ResumeTracking(wayspotAnchors);
}

In your WayspotAnchorsCreated event handler, you need to call WayspotAnchorController.ResumeTracking() on the created anchors to have VPS start tracking the created anchors.

Each successfully created IWayspotAnchor will have a Payload, a binary blob that you should save to use when you want to restore previously created anchors, or to share the anchor with other users. The payload is created by VPS and is only available once the IWayspotAnchor.Status is WayspotAnchorStatusCode.Success or WayspotAnchorStatusCode.Limited. See Persisting and Sharing Wayspot Anchors for how to serialize and deserialize Wayspot Anchors.

Once a Wayspot Anchor has been successfully created, you’ll need to subscribe to the anchor’s TransformUpdated event to get corrections from VPS for the anchor’s position and orientation as the user moves. See Handle Anchor Tracking Updates for how to do this.

Restoring a Previously Created Wayspot Anchor with WayspotAnchorController

To restore a Wayspot Anchor created in a prior VPS session, use WayspotAnchorController.RestoreWayspotAnchors(). You’ll provide a list of anchor payloads that identify which anchors need to be restored, and get back an array of IWayspotAnchors:

using Niantic.ARDK.AR.WayspotAnchors;

// Deserialize/load saved payloads, using WayspotAnchorPayload.Deserialize() as needed
// var payloads = ...load payloads...
if (payloads.Length > 0)
{
    var wayspotAnchors = _wayspotAnchorController.RestoreWayspotAnchors(payloads);

    // Resume tracking restored anchors
    _wayspotAnchorController.ResumeTracking(wayspotAnchors);

    // Add restored IDs and IWayspotAnchors to cache
    foreach (var wayspotAnchor in wayspotAnchors)
    {
        // Look up anchor.ID in our cache, add associated IWayspotAnchor
        if (!_wayspotAnchors.ContainsKey(wayspotAnchor.ID))
        {
            // Check if VPS couldn't restore the anchor
            if (wayspotAnchor.Status == WayspotAnchorStatusCode.Failed) {
                // ...handle failed anchor restore condition...
                continue;
            }
            _wayspotAnchors.Add(wayspotAnchor.ID, wayspotAnchor);
        }
        Debug.Log($"Restored wayspot anchor {wayspotAnchor.ID}");
    }
}

If you need to load previously persisted Wayspot Anchor payloads see Persisting and Sharing Wayspot Anchors for how to serialize and deserialize Wayspot Anchors.

Once a Wayspot Anchor has been successfully restored, you’ll need to subscribe to the anchor’s TransformUpdated event to get corrections from VPS for the anchor’s position and orientation as the user moves. See Handle Anchor Tracking Updates for how to do this.

Pausing Wayspot Anchor Tracking

Your AR experience might use many Wayspot Anchors, however you might not need to track and display associated game objects all the time. For example, you might have a game object used to help players visualize placement during a specific mode of your game, that you don’t need to track (or display) in other game modes. You can pause tracking for VPS Wayspot Anchors in these situations to reduce computational and network overhead.

To pause anchor tracking, use WayspotAnchorController.PauseTracking() with the wayspot anchor IDs that don’t need to be tracked. Once you need to resume tracking these anchors, use WayspotAnchorController.ResumeTracking() with the paused wayspot anchor IDs.

Stopping a VPS Session

If you no longer need to create or track any Wayspot Anchors, you can stop the VPS service without stopping your AR session. You might need to do this if your AR experience needs to provide AR features when your users are not near any VPS-activated Wayspots. For example, if your users are traveling between different VPS-activated Wayspots, but you still want to display some virtual objects using AR depth, or AR meshing.

You might also need to stop and restart a VPS session when your app encounters localization issues. See “Understanding Localization Flow” in Localizing with VPS for examples of when you might need to restart VPS. Also, see “Restarting VPS” in Localizing with VPS for additional details on what happens when you restart a VPS session.

Stop the VPS session using WayspotAnchorController.StopVps(). Any in-progress Wayspot Anchor creation or tracking will be canceled.

Handle Anchor Tracking Updates

As the user moves and changes position and orientation relative to the VPS-activated Wayspot, Lightship VPS automatically updates its understanding of the updated environment. This may result in Lightship VPS making corrections to Wayspot Anchor position and orientation to ensure the Wayspot Anchor stays fixed in the same real-world position. Lightship VPS will send these corrections via the anchor’s TransformUpdated event.

WayspotAnchorTracker is a convenience extension class that can automatically handle anchor position and orientation updates. You can use this class when creating or restoring Wayspot anchors, or extend (or replace) this class if you need to customize how the anchor position and orientation updates are handled.

The following example uses WayspotAnchorTracker to instantiate a prefab (_anchorPrefab) and associate it with a created or restored Wayspot anchor via WayspotAnchorTracker.AttachAnchor().

using Niantic.ARDK.Extensions;

private GameObject CreateWayspotAnchorGameObject(IWayspotAnchor anchor, Vector3 position, Quaternion rotation, bool startActive)
{
  var go = Instantiate(_anchorPrefab, position, rotation);

  var tracker = go.GetComponent<WayspotAnchorTracker>();
  if (tracker == null)
  {
    Debug.Log("Anchor prefab was missing WayspotAnchorTracker, so one will be added.");
    tracker = go.AddComponent<WayspotAnchorTracker>();
  }

  tracker.gameObject.SetActive(startActive);
  tracker.AttachAnchor(anchor);
  // ...Add to a local cache of WayspotAnchorTrackers if needed...

  return go;
}

Once a Wayspot anchor is attached to a WayspotAnchorTracker, the WayspotAnchorTracker will automatically handle IWayspotAnchor.TransformUpdated events and update the game object position and orientation accordingly. If you need to customize how anchor updates are handled, you can override methods in your own class derived from WayspotAnchorTracker. For example, if you wanted the game objects associated with anchors to smoothly interpolate position and orientation changes, you could subclass WayspotAnchorTracker and override WayspotAnchorTracker.OnTransformUpdated() with your own implementation with smoothing.

For an example of extending WayspotAnchorTracker, see the ColorChangingTracker class in the ARDK-Examples project (part of the WayspotAnchors example scene).

If you can’t use WayspotAnchorTracker, you can set your own IWayspotAnchor.TransformUpdated event handler. In your event handler get the ID of the updated anchor through the WayspotAnchorResolvedArgs.ID parameter to determine which IWayspotAnchor was updated.

Note

Currently it’s possible to restore anchors before the session has successfully localized. Restored anchors are not immediately resolved when the session is localized. Once a session has successfully localized, restored anchors will start to resolve anchor position and orientation and send TransformUpdated events.

Persisting and Sharing Wayspot Anchors

To be able to restore Wayspot Anchors, you’ll need to persist the Wayspot Anchor payload. WayspotAnchorPayload has convenience Serialize() and Deserialize() methods you can use that convert the payload data into a Base64 string representation. You can then persist this string in your app, in your cloud, and/or share it with other users.

Wayspot Anchors and Mock Mode

You can place and restore Wayspot Anchors in Virtual Studio Mock Mode. VPS will simulate a fake localization and be localized after 300 milliseconds when you run in Mock Mode in the Unity editor. You can then use WaypointAnchorService or WaypointAnchorController to place and restore Wayspot Anchors, and the Wayspot Anchors API will automatically use a mock anchor implementation for these anchors.

The anchor payloads that are returned for mock anchors should not be used outside of Mock Mode. Attempts to restore an anchor using a mock anchor payload when running on the device will fail. Similarly, anchors created in the real world cannot be restored in Mock Mode.

See Playing in Mock Mode for more details on running in Mock Mode.

Wayspot Anchors Best Practices

When placing Anchors, there may be a very small delay before your app receives the payload for the Anchor. If your user is interactively placing Anchors, we recommend rendering the game objects associated with the Anchor immediately rather than waiting for the returned payload, to avoid any perceived lag with displaying the placed objects.

Wayspot anchor data currently has a lifetime of 6 months. You should track the time when you first create an anchor, and check this time when you restore the anchor. If more than 6 months have elapsed, you should consider re-creating the anchor.