How to Use Neural Network Model Preloading
Awareness features such as Meshing and Depth use neural network models to know how to draw each pixel in an AR session. To improve runtime performance, model preloading allows you to download model files ahead of time, frontloading the installation process and avoiding just-in-time loading delays that can negatively impact the user experience.

Prerequisites
- You will need a Unity project with Lightship AR enabled. For more information, see Installing ARDK 3.0.
Neural Network Performance Modes
Lightship awareness features support a range of performance modes, allowing developers to select for performance, quality, or a balanced mix. These modes are analogous to the Unity EnvironmentDepthMode values used in the XROcclusionSubsystem.
For example, Fast optimizes for faster processing time at the expense of quality, while Smooth takes more time to deliver the best graphics. Each mode has its own neural network model file that can be preloaded before using AR features. For developers who want to supply their own neural network model file, RegisterModel allows for overriding the predefined Lightship models.
To request a feature mode, specify the feature and mode before starting the awareness feature:
DownloadModel(DepthMode.Medium);
DownloadModel(SemanticsMode.Smooth);
See Runtime/Utilities/Preloading/Feature.cs for the definitive list of feature modes.
Preloading a Lightship Neural Network Model
To preload a neural network model file before starting an awareness feature:
- Determine which model you would like to preload based on your application's performance and quality needs.
- Decide when preloading will occur. Preloading can happen any time after AR Foundation has initialized the Lightship loader (when
XRGeneralSettings.Instance.Manager.isInitializationCompleteis true) and before awareness features have started. For example, if your AR script is aMonoBehaviour, preloading can happen duringStart().
Make sure there are no active AR Managers in the scene where you use preloading APIs. If an AR Manager is present, any associated models will download automatically.
Model preloading APIs are only available during runtime after a Lightship AR session has started. If a model is not preloaded, awareness features will automatically choose one when starting.
-
Set up a
Canvaswith UI Objects:- In the Hierarchy, right-click in the main scene, then open the UI menu and select Canvas.
- Repeat this process four more times to add two
Buttonand twoTextobjects. Customize their look in any way you want.
-
Create an empty
GameObjectin the scene where preloading should occur:- In the Hierarchy, right-click the scene, then select Create Empty. Name the new
GameObjectModelPreloader.
- In the Hierarchy, right-click the scene, then select Create Empty. Name the new
-
Add a new script component to the empty:
- Select ModelPreloader in the Hierarchy, then, in the Inspector, click Add Component and add a new script to it.
-
At the top of the script, add serialized fields for the UI Objects:
[SerializeField]
private Button _downloadButton;
[SerializeField]
private Button _clearButton;
[SerializeField]
private Text _progressPercentText;
[SerializeField]
private Text _statusText; -
Attach the GameObjects to the script in the Inspector:
-
Create a private preloader field, set a model feature to download, and add a bool to keep track of the state:
- Instantiate the object with
ModelPreloaderFactoryin theStartmethod:
private IModelPreloader preloader;
private DepthMode _depthMode = DepthMode.Medium;
private bool _isDownloading = false;
private void Start()
{
preloader = ModelPreloaderFactory.Create();
if (null == preloader)
{
// Need to wait for XR to initialize before we can preload.
// Defer preloader instantiation to a later function.
return;
} - Instantiate the object with
-
Call
ExistsInCache()to check if the model already resides in the cache, then set the state of the scene.if (!preloader.ExistsInCache(_depthMode))
{
_statusText.text = $"{_depthMode} model not found in cache";
_progressPercentText.text = "0%";
_clearButton.interactable = false;
_downloadButton.interactable = true;
}
else
{
// The model is already in the cache. No download is required.
_statusText.text = $"{_depthMode} model found in cache";
_progressPercentText.text = "100%";
_clearButton.interactable = true;
_downloadButton.interactable = false;
} -
Create a
Downloadmethod to have the preloader download the model:private void DownloadModel()
{
preloader.DownloadModel(_depthMode);
_isDownloading = true;
_statusText.text = "Downloading model...";
_progressPercentText.text = "0%";
_clearButton.interactable = false;
_downloadButton.interactable = false;
} -
Add a
ClearCachemethod to delete the downloaded model:private void ClearCache()
{
preloader.ClearFromCache(_depthMode);
_statusText.text = $"{_depthMode} model cleared from cache";
_progressPercentText.text = "0%";
_clearButton.interactable = false;
_downloadButton.interactable = true;
} -
Attach
onClicklisteners to the buttons to call their corresponding methods:private void OnEnable()
{
_downloadButton.onClick.AddListener(DownloadModel);
_clearButton.onClick.AddListener(ClearCache);
}
private void OnDisable()
{
_downloadButton.onClick.RemoveListener(DownloadModel);
_clearButton.onClick.RemoveListener(ClearCache);
} -
If you want to display download progress to the user, periodically call
CurrentProgress(). Whenprogressis1.0, model preloading is complete. For example:private void Update()
{
if (!_isDownloading)
{
return;
}
var statusCode = preloader.CurrentProgress(_depthMode, out float progress);
if (Mathf.Approximately(progress, 1.0f))
{
// The download has completed successfully, or the model was already in the cache
_statusText.text = $"{_depthMode} model downloaded successfully";
_progressPercentText.text = "100%";
_clearButton.interactable = true;
_downloadButton.interactable = false;
_isDownloading = false;
return;
}
if (statusCode != PreloaderStatusCode.RequestInProgress)
{
// The download is not in progress
_statusText.text = $"Current status: {statusCode}";
_isDownloading = false;
return;
}
_progressPercentText.text = $"{progress * 100.0f}%";
} -
Test the scene in the Unity Editor and double-check the steps above if something doesn't work.