How to Create a Device Map
This feature is experimental and may not work as expected. For more information about it, see the Device Mapping Feature page.
Before you can use a device map in your AR application, you will need to create and save it. In this tutorial, we will go over how to create and save a device map in your Unity project, as well as some tips for how to get the most out of device mapping.
Prerequisites
You will need a Unity project with ARDK installed and a basic AR scene. For more information, see Setting Up Lightship ARDK and Setting up a Basic AR Scene.
Creating a Device Map
To create and store a device map:
- In the Hierarchy, select the XROrigin, then, in the Inspector, click Add Component and add an
ARDeviceMappingManager
. - In the Hierarchy, right-click the root of your AR scene, then select Create Empty. Name the new object
DeviceMappingDemo
. - Select
DeviceMappingDemo
from the Hierarchy, then, in the Inspector, click Add Component. Search for and add a New Script to it, then name itMapper.cs
. - Open
Mapper.cs
and replace its contents with the following snippet:
using System;
using System.Collections;
using System.IO;
using Niantic.Lightship.AR.Mapping;
using UnityEngine;
using UnityEngine.UI;
public class Mapper : MonoBehaviour
{
}
-
Add UI elements for the mapper:
- Right-click in the Hierarchy, then open the Create menu and select Button from the UI sub-menu. This will create a Canvas element and add the button to it.
-
Add this snippet to the
Mapper
class to map for ten seconds when the button is pressed:[SerializeField]
private ARDeviceMappingManager _deviceMappingManager;
[SerializeField]
private Button _startMappingButton;
private void Start()
{
_startMappingButton.onClick.AddListener(OnStartMappingClicked);
}
// Set this function to be called when button is clicked
public void OnStartMappingClicked()
{
StartCoroutine(RunMapping());
}
private IEnumerator RunMapping()
{
// disable the button after clicking so that only one map is made at a time
_startMappingButton.gameObject.SetActive(false);
_deviceMappingManager.SetDeviceMap(new ARDeviceMap());
_deviceMappingManager.StartMapping();
// change this value to map for more or less time
yield return new WaitForSeconds(10.0f);
_deviceMappingManager.StopMapping();
_startMappingButton.gameObject.SetActive(true);
}
Ten seconds is enough time to map a small area, such as a desk or couch. If you are mapping a larger area, increase the mapping time to compensate.
-
After the UI code, add an event listener for
ARDeviceMappingManager.DeviceMapFinalized
so that we know when to save the map:private const string MapFileNamePrefix = "SerializedDeviceMapData";
private void Start()
{
_deviceMappingManager.DeviceMapFinalized += OnDeviceMapFinalized;
}
private void OnDeviceMapFinalized(ARDeviceMap map)
{
if (map.HasValidMap())
{
// final map generated. save to the file system
var serializedDeviceMap = map.Serialize();
var path = Path.Combine(Application.persistentDataPath, MapFileName);
File.WriteAllBytes(path, serializedDeviceMap);
Debug.Log($"Map saved");
}
else
{
Debug.LogError("Map was empty");
}
}
A final device map will be generated after StopMapping()
is called, but it will not be available until the DeviceMapFinalized
event is invoked. Make sure to wait for the finalized event after the button is pressed!
Optional: Show the Mesh While Mapping
By default, ARDeviceMappingManager
does not provide any visual feedback while mapping an area. By adding meshing to your project, you can visualize your map's coverage and get a sense of where you still need to cover. The mesh cannot exactly show where the device map was generated or its localizability, but it can provide a general idea of the map's area. To learn about how to add meshing to your Lightship project, see Creating a Mesh.
Device Mapping Tips
- Because device mapping relies on a single scan, localization and tracking accuracy depend heavily on how well you scan the area. If you remember one tip, let it be this: if you are having localization issues, don't be afraid to re-scan!
- Lighting matters a lot when scanning an area. If the lighting during localization doesn't match the scan, you will need to re-scan. (This includes both outdoor and indoor lighting!)
- For best results, follow these guidelines when scanning:
- Focus on distinctive objects in the area that are unlikely to move between scanning and localization, such as furniture, household fixtures, or statues.
- Avoid looking primarily at flat surfaces without color variation, such as the ground, grass, walls, and floors.
- Move around while scanning! The more viewpoints you see an object from, the better the map of it will be.
Complete Device Mapping Script
If you are having trouble with your mapping script, compare it to the finished product here!
Click here to reveal the final Mapper.cs script
using System;
using System.Collections;
using System.IO;
using Niantic.Lightship.AR.Mapping;
using UnityEngine;
using UnityEngine.UI;
public class Mapper : MonoBehaviour
{
public const string MapFileName = "SerializedDeviceMapData";
[SerializeField]
private ARDeviceMappingManager _deviceMappingManager;
[SerializeField]
private Button _startMappingButton;
private void Start()
{
_deviceMappingManager.DeviceMapFinalized += OnDeviceMapFinalized;
_startMappingButton.onClick.AddListener(OnStartMappingClicked);
}
private void OnDeviceMapFinalized(ARDeviceMap map)
{
if (map.HasValidMap())
{
// final map generated. save to the file system
var serializedDeviceMap = map.Serialize();
var path = Path.Combine(Application.persistentDataPath, MapFileName);
File.WriteAllBytes(path, serializedDeviceMap);
Debug.Log($"Map saved");
}
else
{
Debug.LogError("Map was empty");
}
}
// Set this function to be called when button is clicked
public void OnStartMappingClicked()
{
StartCoroutine(RunMapping());
}
private IEnumerator RunMapping()
{
_startMappingButton.gameObject.SetActive(false);
_deviceMappingManager.SetDeviceMap(new ARDeviceMap());
_deviceMappingManager.StartMapping();
yield return new WaitForSeconds(10.0f);
_deviceMappingManager.StopMapping();
_startMappingButton.gameObject.SetActive(true);
}
}
Next Steps
Once you have created and saved a device map, move on to How to Place Real-World Content Using a Device Map.