How to Use Shared AR
You can use these steps to setup a shared AR room using VPS. You will need to add the proper components to your Unity scene. Then you can use the CoverageAPI or the ARLocationManager to create a shared AR room.
Prerequisites
- You will need a Unity project with Lightship AR enabled.
- You will need to install the Shared AR plugin.
- You will need an AR scene with ARSession and XROrigin.
Add Components to your Scene
You will need to add these components to your Unity scene in order to use Shared AR:
- Add a Network Manager object to the root of your scene.
- In the Hierarchy, select the scene title.
- From the main menu, select GameObject and select Create Empty
- Name the object NetworkManager.
- Add a NetworkManager component to the object.
-
In the Hierarchy, select the NetworkManager.
-
In the Inspector window, click Add Component.
-
Type "Network Manager" into the search box and select it to add.
-
Under Network Transport, click Select transport... and select LightshipNetcodeTransport. This will automatically add the Lightship Netcode Transport component.
-
- Add a SharedSpaceManager component to XROrigin
- In your AR Scene in the Hierarchy, select the XR Origin component.
- In the Inspector window, click Add Component.
- Type "Shared Space Manager" into the search box and select it to add.
- Make sure Colocalization Type is set to Vps Colocalization.
Using SharedSpaceManager with the Coverage API
You can join a shared room at any VPS location using the Coverage API. You start by using TryGetCoverage to get AreaTargets. This will give you a list of nearby VPS locations to choose from. VPS Locations are defined as a LocalizationTarget.DefaultAnchor. Once your user has chosen a location, you can join a Room using SharedSpaceManager using the DefaultAnchor
as the room identifier.
Using TryGetCoverage to get AreaTargets
You can use the CoverageClientManager class to get a list of nearby VPS locations. Locations are defined as a LocalizationTarget.DefaultAnchor. These are the basic steps:
-
Instantiate a copy of Niantic.Lightship.AR.CoverageClientManager:
...
using Niantic.Lightship.AR;
public class CoverageClientSelector : MonoBehaviour
{
// References to components
[SerializeField]
public CoverageClientManager CoverageClient;
...
} -
Declare an event handler that takes an
AreaTargetsResult
. This sample handler puts the 5 nearest locations into a dictionary.private Dictionary<string, string> LocationToPayload = new();
private void OnGottenCoverage(AreaTargetsResult args)
{
var areaTargets = args.AreaTargets;
// Sort the area targets by proximity to the user
areaTargets.Sort((a, b) =>
a.Area.Centroid.Distance(args.QueryLocation).CompareTo(
b.Area.Centroid.Distance(args.QueryLocation)));
// Populate the dictionary with the 5 nearest names and anchors
for (var i = 0; i < 5; i++)
{
LocationToPayload[areaTargets[i].Target.Name] = areaTargets[i].Target.DefaultAnchor;
}
} -
Add the event handler to
CoverageClient.TryGetCoverage
.void Start()
{
CoverageClient.TryGetCoverage(OnGottenCoverage);
}
The CoverageClientSelector sample script shows how to use the process to populate a Unity Dropdown box. For a full example of the CoverageClient with a complete UI (including image targets and distance from device), see the Shared AR VPS sample.
Click to show the CoverageClientSelector code sample
using System.Collections.Generic;
using System.Linq;
using Niantic.Lightship.AR;
using Niantic.Lightship.AR.VpsCoverage;
using UnityEngine;
using UnityEngine.UI;
public class CoverageClientSelector : MonoBehaviour
{
// References to components
[SerializeField]
public CoverageClientManager CoverageClient;
[SerializeField]
public Dropdown DropdownSelector;
// This will be populated by selecting an area target by name in the UI dropdown
public string SelectedPayload;
private Dictionary<string, string> LocationToPayload = new();
void Start()
{
CoverageClient.TryGetCoverage(OnGottenCoverage);
DropdownSelector.onValueChanged.AddListener(OnValueChanged);
}
private void OnValueChanged(int arg)
{
SelectedPayload = LocationToPayload[DropdownSelector.options[arg].text];
}
private void OnGottenCoverage(AreaTargetsResult args)
{
// Clear any previous data
DropdownSelector.ClearOptions();
LocationToPayload.Clear();
SelectedPayload = null;
var areaTargets = args.AreaTargets;
// Sort the area targets by proximity to the user
areaTargets.Sort((a, b) =>
a.Area.Centroid.Distance(args.QueryLocation).CompareTo(
b.Area.Centroid.Distance(args.QueryLocation)));
// Only populate the dropdown with the closest 5 locations.
// For a full sample with UI and image hints, see the VPSColocalization sample
for (var i = 0; i < 5; i++)
{
LocationToPayload[areaTargets[i].Target.Name] = areaTargets[i].Target.DefaultAnchor;
}
DropdownSelector.AddOptions(LocationToPayload.Keys.ToList());
}
}
Joining a Room using SharedSpaceManager
You can use a LocalizationTarget.DefaultAnchor to join a Shared AR room as a host or a client. These are the basic steps:
- Instantiate a copy of the
SharedSpaceManager
. - Take the
DefaultAnchor
from the selected location (defaultPayloadToSet)
and pass it to theSharedSpaceManager.StartTracking
andSharedSpaceManager.PrepareRoom
methods.[SerializeField]
private SharedSpaceManager _sharedSpaceManager;
private void OnLocationSelected(string defaultPayloadToSet)
{
var vpsTrackingOptions = ISharedSpaceTrackingOptions.CreateVpsTrackingOptions(defaultPayloadToSet);
var roomOptions = ISharedSpaceRoomOptions.CreateVpsRoomOptions(
vpsTrackingOptions,
"optionalPrefixForRoom_",
10,
"Room Description Here!"
);
_sharedSpaceManager.StartSharedSpace(vpsTrackingOptions, roomOptions);
} - Setup an event listener for
SharedSpaceManager.sharedSpaceManagerStateChanged
. Whenargs.Tracking
is true, there is a shared space you can join. This sample uses a "Join as Host" and "Join as Client" button to set active when the user can join:[SerializeField]
private Button _joinAsHostButton;
[SerializeField]
private Button _joinAsClientButton;
protected void Start()
{
_sharedSpaceManager.sharedSpaceManagerStateChanged += OnColocalizationTrackingStateChanged;
}
private void OnColocalizationTrackingStateChanged(
SharedSpaceManager.SharedSpaceManagerStateChangeEventArgs args)
{
if (args.Tracking)
{
_joinAsHostButton.gameObject.SetActive(true);
_joinAsClientButton.gameObject.SetActive(true);
}
} - To join as a host, call
NetworkManager.Singleton.StartHost
. To join as a client, callStartClient
.protected void Start()
{
_joinAsHostButton.onClick.AddListener(OnJoinAsHostClicked);
_joinAsClientButton.onClick.AddListener(OnJoinAsClientClicked);
}
private void OnJoinAsHostClicked()
{
NetworkManager.Singleton.StartHost();
HideButtons();
}
private void OnJoinAsClientClicked()
{
NetworkManager.Singleton.StartClient();
HideButtons();
}
private void HideButtons()
{
_joinAsHostButton.gameObject.SetActive(false);
_joinAsClientButton.gameObject.SetActive(false);
}
Make sure the first user is the Host and the rest are Clients.
Using SharedSpaceManager with ARLocationManager
If you have followed the steps in How to Place Content in Real-World Locations Using Location AR to add an ARLocation to your scene, you can use that location when you call SharedSpaceManager.PrepareRoom. For example:
public SharedSpaceManager SharedSpaceManager;
public ARLocationManager ARLocationManager;
...
// Start is called before the first frame update
void Start()
{
// This demo only targets a single ARLocation, so we can just use the first location.
// For applications that choose from a list, use the specific ARLocation that you are localizing against
// as the room ID
var vpsTrackingOptions = ISharedSpaceTrackingOptions.CreateVpsTrackingOptions(ARLocationManager.ARLocations.First());
var roomOptions = ISharedSpaceRoomOptions.CreateLightshipRoomOptions(
ARLocationManager.ARLocations.First().Payload.ToBase64(),
10,
"Room Description Here!"
);
_sharedSpaceManager.StartSharedSpace(vpsTrackingOptions, roomOptions);
}
You can then call NetworkManager.Singleton.StartHost
or StartClient
to join the room.
The VPSLocationDemoManager sample script shows how to use SharedSpaceManager with an ARLocationManager. It also assumes you have a ConnectionUI
object to handle the user interface. For a full example of the SharedSpaceManager, see the VpsColocalizationDemo.cs
script in the Shared AR VPS sample.
Click to show the VPSLocationDemoManager code sample
using System.Linq;
using Niantic.Lightship.AR.Subsystems;
using Niantic.Lightship.SharedAR.Colocalization;
using Unity.Netcode;
using UnityEngine;
public class VPSLocationDemoManager : MonoBehaviour
{
public SharedSpaceManager SharedSpaceManager;
public ARLocationManager ARLocationManager;
public GameObject ConnectionUI;
private bool _started;
// Start is called before the first frame update
void Start()
{
SharedSpaceManager.sharedSpaceManagerStateChanged += OnSharedSpaceStateChanged;
// This demo only targets a single ARLocation, so we can just use the first location.
// For applications that choose from a list, use the specific ARLocation that you are localizing against
// as the room ID
var vpsTrackingOptions = ISharedSpaceTrackingOptions.CreateVpsTrackingOptions(ARLocationManager.ARLocations.First());
var roomOptions = ISharedSpaceRoomOptions.CreateLightshipRoomOptions(
ARLocationManager.ARLocations.First().Payload.ToBase64(),
10,
"Room Description Here!"
);
_sharedSpaceManager.StartSharedSpace(vpsTrackingOptions, roomOptions);
}
private void OnSharedSpaceStateChanged(SharedSpaceManager.SharedSpaceManagerStateChangeEventArgs args)
{
if (args.Tracking && !_started)
{
ConnectionUI.SetActive(true);
_started = true;
}
}
public void StartAsHost()
{
NetworkManager.Singleton.StartHost();
ConnectionUI.SetActive(false);
}
public void StartAsClient()
{
NetworkManager.Singleton.StartClient();
ConnectionUI.SetActive(false);
}
}
Next Steps
See How to Display Shared Objects for information on how to display shared objects in the same room, or display objects in the location of each player in the room.