Skip to main content

How to Use Location AR with Code

Using Location AR With Code

This how-to covers:

  • Managing and tracking ARLocations through the ARLocationManager public API
  • Listening for updates to registered ARLocations
  • Placing content relative to an ARLocation
  • Swapping tracked ARLocations during an AR Session

Prerequisites

  1. You will need a Unity project with ARDK installed and a set-up basic AR scene. For more information, see Setup ARDK 3 and Setting up a Basic AR Scene.
  2. If you have not added one, you will need a valid API Key.
  3. Your project must have an ARLocationManager in its AR scene to use this How-To. See Step 4 of Adding a Real-World Location to Unity to learn how to add an ARLocationManager and an ARLocation to your project. (For Swapping ARLocations, you will need more than one ARLocation.)

Registering ARLocations to be Tracked

To add an ARLocation to the ARLocationManager, set it by calling SetARLocations on the ARLocationManager.

Each time this is called, all previously set locations will be cleared. SetARLocations() can only be called before calling StartTracking(). After setting the ARLocations to be tracked, call StartTracking() on the ARLocationManager to start tracking attempts.

After setting which locations will be tracked, call StartTracking() on the ARLocationManager to start tracking attempts.

note

While up to five ARLocations can be registered simultaneously, only the first one to successfully track will report updates. Attempting to track multiple locations simultaneously will also increase the network bandwidth usage of tracking. It is recommended to only register a single ARLocation to be tracked if you know where the user is located or are targeting a location for tracking. Registering multiple locations is useful if you are unsure exactly what the tracking target will be.

using Niantic.Lightship.AR.LocationAR;
using UnityEngine;

public class ARLocationTracking : MonoBehaviour
{
[SerializeField]
private ARLocationManager ArLocationManager;

[SerializeField]
private ARLocation[] ArLocations;

public void StartTracking()
{
ArLocationManager.SetARLocations(ArLocations);
ArLocationManager.StartTracking();
}
}

Listening for Updates to Registered ARLocations

To receive and process updates to registered ARLocations, subscribe to locationTrackingStateChanged.

The event arguments contain the updated ARLocation and a bool called Tracking to report their current tracking state. If multiple locations are registered, only the first ARLocation to become tracked will fire events. All other ARLocations will be automatically removed from the tracking list.

Click to reveal the updated ARLocationTracking script
using Niantic.Lightship.AR.LocationAR;
using UnityEngine;
using Niantic.Lightship.AR.PersistentAnchors;

public class ARLocationTracking : MonoBehaviour
{
[SerializeField]
private ARLocationManager ArLocationManager;

[SerializeField]
private ARLocation[] ArLocations;

private bool firstTrackingUpdateReceived = false;

public void StartTracking()
{
ArLocationManager.locationTrackingStateChanged += OnLocationTrackingStateChanged;
ArLocationManager.SetARLocations(ArLocations);
ArLocationManager.StartTracking();
}

private void OnLocationTrackingStateChanged(ARLocationTrackedEventArgs args)
{
var trackedLocation = args.ARLocation;
var isTracking = args.Tracking;

if (!firstTrackingUpdateReceived && isTracking){
Debug.Log("First tracking update received");
firstTrackingUpdateReceived = true;
}

trackedLocation.gameObject.SetActive(isTracking);
}
}

In this snippet, the ARLocation GameObject will be enabled and disabled depending on the tracking state. This is useful to handle loss of tracking when the ARLocation virtual content is no longer tracking properly and may be offset from the AR camera feed.

Placing Content Relative to the ARLocation

Virtual content spawned relative to the ARLocation at runtime should be children of the ARLocation GameObject. This ensures that any tracking updates to the ARLocation will update virtual content as well. Also, using local transform methods (localPosition, localRotation) instead of global transforms (position, rotation) helps virtual content to stay relative to the ARLocation. Local transforms relative to the ARLocation can be stored and retrieved in a future session to place virtual content in the same location.

Click to reveal the ARLocationPlacement script
using Niantic.Lightship.AR.LocationAR;
using UnityEngine;

public class ARLocationPlacement : MonoBehaviour
{
[SerializeField]
private GameObject GameAsset;

// An ARLocation that is already tracking
private ARLocation ArLocation;

// Instantiate an object at some provided pose in world space (ie, the results of a hit test against a plane)
public GameObject SpawnObjectFromHitTest(Vector3 position, Quaternion rotation)
{
var go = Instantiate(GameAsset, position, rotation);

// Retain the previously set pose, but child the asset to the ARLocation
go.transform.SetParent(ArLocation.transform, true);

return go;
}

public void UpdateObjectPosition(Vector3 localPosition, Quaternion localRotation, GameObject go)
{
go.transform.localPosition = localPosition;
go.transform.localRotation = localRotation;
}
}

Updating Tracking When Content Is Misaligned

Over time, drift in the ARSession or losing AR tracking can cause ARLocations to be misaligned with the real world. In the case of ARLocation tracking loss, the ARLocationManager will automatically attempt to reconnect with the ARLocation upon regaining tracking. However, not all tracking loss events are reported or handled. To manually trigger ARLocation tracking, call TryUpdateTracking() on the ARLocationManager.

Click to reveal the updated ARLocationTracking script
using Niantic.Lightship.AR.LocationAR;
using UnityEngine;

public class ARLocationTracking : MonoBehaviour
{
[SerializeField]
private ARLocationManager ArLocationManager;

// This can be attached to a button, or called on a timer
// Requires that an ARLocation has been previously tracked
public void UpdateTracking()
{
ArLocationManager.TryUpdateTracking();
}
}

Stopping Location Tracking

ARLocation tracking can be stopped by calling StopTracking() on the ARLocationManager. This will remove any ARPersistentAnchors associated with tracked locations, set all locations to inactive, and return each ARLocation to its original parent in the Hierarchy if it still exists. To avoid leaking GameObjects between tracking sessions, we recommend despawning and destroying any instantiated GameObjects before calling StopTracking().

Click to reveal the StopTracking code snippet
using Niantic.Lightship.AR.LocationAR;
using UnityEngine;

public class ARLocationTracking : MonoBehaviour
{
[SerializeField]
private ARLocationManager ArLocationManager;

// GameObjects spawned at runtime
private GameObject[] SpawnedGameObjects;

public void StopTracking()
{
foreach (var go in SpawnedGameObjects)
{
Destroy(go);
}

ArLocationManager.StopTracking();
}
}

Swapping Locations Using Code

ARLocations can only be swapped when tracking is stopped. This can be used to update a tracked ARLocation, such as when the user moves to a new location. After calling StopTracking(), set a new ARLocation to be tracked and call StartTracking(). If no SetARLocations call is made, the previous set of ARLocations will be used.

Click to reveal the location swapping code snippet
using System.Collections;

using Niantic.Lightship.AR.LocationAR;
using UnityEngine;

public class ARLocationTracking : MonoBehaviour
{
[SerializeField]
private ARLocationManager ArLocationManager;

// Already being tracked
[SerializeField]
private ARLocation InitialLocation;

[SerializeField]
private ARLocation SecondLocation;

public void UpdateLocationForTracking()
{
StartCoroutine(UpdateLocationCoroutine());
}

private IEnumerator UpdateLocationCoroutine()
{
ArLocationManager.StopTracking();
ArLocationManager.SetARLocations(SecondLocation);

// Wait a frame to clear native systems and tracking
yield return null;
ArLocationManager.StartTracking();
}
}

More Information