Skip to main content

How to Set Up a Shared AR Scene with Netcode

Shared AR is a set of AR and network features that allows you to create mulitplayer AR experiences. In this How-To, you will learn to set up network multiplayer, enable real-world tracking, and connect to the Lightship Network Server using Unity Netcode for GameObjects.

SharedAR Set up video

Prerequisites

  1. You will need a Unity project with Lightship AR enabled.
  2. You will need to install the Shared AR plugin.
  3. You will need an AR scene with ARSession and XROrigin.
  4. Familiarize with concepts and usage of Netcode for Gameobjects from Get started with NGO in the Unity documentation.

Add Components to your Scene

You will need to add these components to your Unity scene in order to use Shared AR:

  1. Add a Network Manager object to the root of your scene.

    1. In the Hierarchy, select the scene title.
    2. From the main menu, select GameObject and select Create Empty
    3. Name the object NetworkManager.
  2. Add a NetworkManager component to the object.

    1. In the Hierarchy, select the NetworkManager.

    2. In the Inspector window, click Add Component.

    3. Type "Network Manager" into the search box and select it to add.

    4. Under Network Transport, click Select transport... and select LightshipNetcodeTransport. This will automatically add the Lightship Netcode Transport component.

      Add Lightship Netcode Transport
  3. Add a SharedSpaceManager component to XROrigin

    1. In your AR Scene in the Hierarchy, select XR Origin.

    2. In the Inspector window, click Add Component.

    3. Type "Shared Space Manager" into the search box and select it to add one to the XR Origin.

    4. Set Colocalization Type in the Shared Space Manager to Mock Colocalization. Make sure to change this to the corresponding Colocalization Type when using VPS Colocalization or Image Tracking Colocalization.

      Mock colocalization in SharedSpaceManager

Starting a Netcode Session with SharedSpaceManager

Using SharedSpaceManager, we will next set up the scene and code to let users connect to one another and begin a networked session.

To set up the UI and managers for SharedAR:

  1. In the Hierarchy, right-click under your AR scene, then open the UI menu and select Button - TextMeshPro to add a button. Repeat this process, adding another button and a text field. The buttons will allow hosts and clients to join, while the text field is for connection status output. Name the buttons JoinAsHost and JoinAsClient, then name the text field LocalizationStatusText.

  2. Still in the Hierarchy, right-click the root of your AR scene, then select Create Empty. Name the new object NetworkDemo.

  3. In the Assets folder of the Project window, right-click, then open the Create menu and select C# Script. Name the new script NetworkDemoManager.cs.

    1. Create a new C# script in your project and name it to NetworkDemoManager.cs
    2. Open NetworkDemoManager.cs and add this code snippet to it to initialize the UI elements and SharedSpaceManager:
    [SerializeField]
    private Text _statusText;

    [SerializeField]
    private Button _joinAsHostButton;

    [SerializeField]
    private Button _joinAsClientButton;

    [SerializeField]
    private SharedSpaceManager _sharedSpaceManager;
  4. Connect the fields in NetworkDemoManager.cs to NetworkDemo:

    1. In your AR Scene in the Hierarchy, select the NetworkDemo component.

    2. In the Inspector window, click Add Component.

    3. Type "Network Demo Manager" into the search box and select it to add.

    4. Drag and drop the text field, buttons, and the XR Origin that now contains a SharedSpaceManager from the Hierarchy into the corresponding fields in the Network Demo Manager Component. At this point, this is how NetworkDemo should look:

      Mock colocalization in SharedSpaceManager

Creating a Room and Handling Events

Next, we will add code to the script to create a multiplayer room and handle shared AR events, such as incoming user connections. To get the Network Demo Manager ready for multiplayer:

  1. Add a code snippet to NetworkDemoManager.cs that will get it ready for connections to the Room:

    1. Create the tracking options for the Room by calling ISharedSpaceTrackingOptions.CreateMockTrackingOptions().

    2. Instantiate the multiplayer Room by creating its room options using ISharedSpaceRoomOptions.CreateLightshipRoomOptions().

    3. Add a handler for the sharedSpaceManagerStateChanged event to the SharedSpaceManager. Copy in this code snippet to add this functionality to NetworkDemoManager.cs:

      protected void Start()
      {
      // Set room to join
      var mockTrackingArgs = ISharedSpaceTrackingOptions.CreateMockTrackingOptions();
      var roomArgs = ISharedSpaceRoomOptions.CreateLightshipRoomOptions(
      "ExampleRoom", // use fixed room name
      32, // set capacity to max
      "vps colocalization demo (mock mode)" // description
      );
      _sharedSpaceManager.StartSharedSpace(mockTrackingArgs, roomArgs);
      }

Next, we will go over some important events and add event-handling code to the Network Demo Manager script:

  1. When the tracking status changes, SharedSpaceManager.sharedSpaceManagerStateChanged is invoked. Watching this event and waiting for a good tracking state before proceeding lets users focus on getting tracking working before the experience begins and reduces the chance that visual content moves inappropriately. In Mock Colocalization Mode, this event is invoked immediately.

  2. When a connection is established, NetworkManager.OnClientConnectedCallback is invoked. Here, we set a callback to the singleton version, NetworkManager.Singleton.OnClientConnectedCallback, so that the host catches incoming player connections. (If the player is a client, this event will instead fire when a host joins.) For this example, we also add text that notifies the user of new connections.

  3. To start a Netcode session as a host, call NetworkManager.Singleton.StartHost. To instead start as a client, call NetworkManager.Singleton.StartClient. For this example, we add these events to their respective buttons, allowing users to join as hosts or clients as appropriate.

    protected void Start()
    {
    // UI event listeners
    _joinAsHostButton.onClick.AddListener(OnJoinAsHostClicked);
    _joinAsClientButton.onClick.AddListener(OnJoinAsClientClicked);

    // Netcode connection event callback
    NetworkManager.Singleton.OnClientConnectedCallback += OnClientConnectedCallback;

    // Set SharedSpaceManager and start it
    _sharedSpaceManager.sharedSpaceManagerStateChanged += OnColocalizationTrackingStateChanged;
    // Set room to join
    var mockTrackingArgs = ISharedSpaceTrackingOptions.CreateMockTrackingOptions();
    var roomArgs = ISharedSpaceRoomOptions.CreateLightshipRoomOptions(
    "ExampleRoom", // use fixed room name
    32, // set capacity to max
    "vps colocalization demo (mock mode)" // description
    );
    _sharedSpaceManager.StartSharedSpace(mockTrackingArgs, roomArgs);
    }

    private void OnColocalizationTrackingStateChanged(
    SharedSpaceManager.SharedSpaceManagerStateChangeEventArgs args)
    {
    if (args.Tracking)
    {
    _joinAsHostButton.gameObject.SetActive(true);
    _joinAsClientButton.gameObject.SetActive(true);
    }
    }
    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);
    }

    private void OnClientConnectedCallback(ulong clientId)
    {
    Debug.Log($"Client connected: {clientId}");
    }
caution

Make sure one user is the Host and the rest are Clients.

Final Network Demo Manager Script

At this point, NetworkDemoManager.cs should look like this:

Click to reveal the finished Network Demo Manager code
using Niantic.Lightship.SharedAR.Colocalization;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.UI;

public class NetworkDemoManager : MonoBehaviour
{
[SerializeField]
private Text _statusText;

[SerializeField]
private Button _joinAsHostButton;

[SerializeField]
private Button _joinAsClientButton;

[SerializeField]
private SharedSpaceManager _sharedSpaceManager;

protected void Start()
{
// UI event listeners
_joinAsHostButton.onClick.AddListener(OnJoinAsHostClicked);
_joinAsClientButton.onClick.AddListener(OnJoinAsClientClicked);

// Netcode connection event callback
NetworkManager.Singleton.OnClientConnectedCallback += OnClientConnectedCallback;

// Set SharedSpaceManager and start it
_sharedSpaceManager.sharedSpaceManagerStateChanged += OnColocalizationTrackingStateChanged;
// Set room to join
var mockTrackingArgs = ISharedSpaceTrackingOptions.CreateMockTrackingOptions();
var roomArgs = ISharedSpaceRoomOptions.CreateLightshipRoomOptions(
"ExampleRoom", // use fixed room name
32, // set capacity to max
"shared ar demo (mock mode)" // description
);
_sharedSpaceManager.StartSharedSpace(mockTrackingArgs, roomArgs);
}

private void OnColocalizationTrackingStateChanged(
SharedSpaceManager.SharedSpaceManagerStateChangeEventArgs args)
{
// Show Join UI
if (args.Tracking)
{
_joinAsHostButton.gameObject.SetActive(true);
_joinAsClientButton.gameObject.SetActive(true);
}
}
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);
}

private void OnClientConnectedCallback(ulong clientId)
{
_statusText.text = $"Connected: {clientId}";
}
}

SharedAR Set up video

Next Steps

See How to use VPS Colocalization with Netcode for information on how to start AR Multiplayer using VPS Colocalization with Netcode.