Develop

Unity Inference Engine

Updated: Jul 8, 2026

Learning objectives

  • Understand how to configure and run AI models directly on-device using the Unity Inference Engine.
  • Learn how to convert, serialize, and quantize .onnx models into optimized .sentis assets for faster performance.
  • Implement model warm-up routines to prevent stutters and ensure smooth runtime initialization.
  • Optimize inference with GPU-based Non-Max Suppression (NMS) and Split Over Frames scheduling.
  • How to transform 2D object detections into spatially anchored 3D visualizations using DepthTextureAccess.
  • Run on-device SLMs with Unity Inference Engine.
On-device inference allows AI models to run directly on Meta Quest headsets, eliminating network dependencies and enabling low-latency processing. This capability is powered by the Unity Inference Engine (formerly Unity Sentis), which executes ONNX or Sentis models efficiently on CPU or GPU backends. Running inference on-device enables instant feedback, offline operation, and complete data privacy.

Why run models on-device

BenefitDescription
Offline Operation
Works fully offline — essential for exhibitions, enterprise, and privacy-sensitive apps.
Ultra-Low Latency
All computation runs locally, removing network delays.
Full Privacy
Sensitive inputs like passthrough images never leave the device.
Deterministic Performance
Performance remains stable regardless of network or server load.

The UnityInferenceEngineProvider

The UnityInferenceEngineProvider is the bridge between Unity and the on-device inference runtime. It wraps your AI model asset (for example, .onnx or .sentis) and provides configuration options for execution backend, frame scheduling, and GPU-based post-processing.
Task Support
UnityInferenceEngineProvider supports three tasks:
  • ObjectDetection - Bounding box detection with NMS
  • ImageSegmentation - Segmentation masks for supported vision models
  • Chat - On-device Small Language Models (SLM)

Inspector parameters

FieldDescription
Use Streaming Asset
Load models as serialized asset from StreamingAssets folder.
Model Asset
The trained model file (.onnx or .sentis).
Backend Type
Choose between CPU and GPUComputebackends.
Split Over Frames
Run a portion of the model per frame to maintain framerate.
Layers Per Frame
Number of layers to execute each frame (used when Split Over Frames is true).
NMS Compute Shader
Optional GPU Non-Max Suppression for bounding box filtering.
Class Labels File
Optional .txt file mapping class indices to readable labels.
LLM Config
Fill OnDeviceLlmConfig for chat mode with tokenizer settings (see On-Device SLM Chat below).

Model conversion, serialization, and quantization

This guide is for when you are planning to use your own models for the Object Detection Building Block, for example. Converting, serializing, and quantizing your models are key steps to prepare them for efficient runtime execution in Unity. These optimizations ensure faster load times, lower memory usage, and consistent performance across devices. The following sections explain how to clean up ONNX models, convert them into Unity’s optimized .sentis format, and optionally serialize or quantize them for deployment.
To make this process easier, Meta provides an editor window located at Meta → Tools → Unity Inference Engine → ONNX → Sentis Converter, which allows you to import, clean up, quantize, and export your ONNX models as optimized .sentis assets with just a few clicks. The following sections explain how to use this tool and how to serialize or quantize models for deployment.

1. Quantize to reduce size

Quantization compresses your model by storing weights in lower precision formats (Float16 or Uint8). This reduces file size and memory usage with minimal accuracy loss.
TypeBitsDescription
None
32
Full precision (default)
Float16
16
Half precision, preserves most accuracy
Uint8
8
Highly compact, may slightly reduce accuracy
You can quantize and serialize models directly from code:
using Unity.InferenceEngine;
using UnityEngine;

public class ModelConverter : MonoBehaviour
{
    public void QuantizeAndSave(Model model, string path)
    {
        ModelQuantizer.QuantizeWeights(QuantizationType.Float16, ref model);
        ModelWriter.Save(path, model);
    }
}

2. Convert your model

Most ONNX models require cleanup before use in Unity. Use Meta → Tools → Unity Inference Engine → ONNX → Sentis Converter to:
  1. Import your .onnx model.
  2. Choose your Quantization Type (None, Float16, Uint8).
  3. Enter the desired path and name of your converted model
  4. Press Convert to Sentis.
This generates a .sentis asset optimized for the Unity runtime.

3. Serialize and load models

Optionally, for large models, create a serialized asset to speed up loading:
  1. In the Project window, select your ONNX model.
  2. In the Inspector, click Serialize to StreamingAssets.
  3. Unity generates a .sentis file inside your StreamingAssets folder.
You can then load it at runtime:
using Unity.InferenceEngine;
Model model = ModelLoader.Load(Application.streamingAssetsPath + "/mymodel.sentis");

Advantages of serialization

Serialized model checkbox
The provider asset can load a serialized asset from the StreamingAssets path automatically. Serialize your model, enable Use Streaming Asset, and assign the serialized model in the Inspector.
  • Faster load times and smaller project size
  • Unity-validated format (guaranteed compatibility)
  • Easier to share between projects

Runtime initialization and warm-up

When a model first runs, Unity Inference Engine must allocate buffers, compile GPU kernels, and upload weights. This can cause a one-time delay of several seconds at startup.
Always perform a warm-up inference during loading or splash screens:
using Unity.InferenceEngine;
using UnityEngine;
using System.Collections;

public class ModelWarmup : MonoBehaviour
{
    [SerializeField] private ModelAsset modelAsset;
    [SerializeField] private BackendType backendType = BackendType.CPU;

    private void Start()
    {
        StartCoroutine(WarmUpModel());
    }

    private IEnumerator WarmUpModel()
    {
        var model = ModelLoader.Load(modelAsset);
        var worker = new Worker(model, backendType);
        var input = new Tensor<float>(new TensorShape(1, 3, 224, 224));
        worker.Schedule(input);
        yield return null;
        worker.Dispose();
        input.Dispose();
        Debug.Log("Model warmed up and ready");
    }
}

Best practices

  • Warm up before gameplay starts.
  • Keep the worker alive across frames.
  • Dispose workers only on scene unload.
  • For multiple models (for example, STT + detection), warm them up sequentially.
Auto-Warmup
LlmAgent, ObjectDetectionAgent, and ImageSegmentationAgent warm up assigned on-device providers during initialization to reduce first-inference latency. The UnityInferenceEngineProvider includes a WarmUp() method you can call manually for other agents.

For vision tasks: Non-Max Suppression (NMS)

Vision-based tasks such as object detection often output multiple overlapping boxes for the same object. Non-Max Suppression (NMS) filters these out, keeping only the most confident ones.

How to efficiently run NMS on the GPU

Some ONNX models include a CPU-based NonMaxSuppression op, like YoloX, which can cause performance bottlenecks. If you have ever tried to run Yolo on the CPU backend, or GPU for that matter, you have likely experienced significant frame drops. Furthermore, on the GPUCompute backend, you will notice that the detection results are not filtered at all, which leads to the model outputting a large number of bounding boxes for the same object.
To tackle this, you can post-process detections using the provided GPU NMS implementation:
  • GpuNMS.cs
  • NMSCompute.compute
These run NMS entirely on the GPU for model outputs that expose boxes, class IDs, and scores. For YOLO-style models with raw output tensors, open the provider asset, expand YOLO-style Model Optimization, assign the model, enable Convert Outputs, choose a quantization option if needed, and click Optimize and Save Model. This converts raw YOLO outputs into the output tensors expected by AI Building Blocks and can also quantize the model.
CPU Bottlenecks with Unity Inference Engine
You might still notice performance spikes when running on the GPUCompute backend. Object detection can require CPU/GPU synchronization while results are filtered and converted into 3D bounding boxes. This bottleneck will be resolved in a future release.

On-Device SLM Chat

The UnityInferenceEngineProvider supports on-device text generation with decoder-only transformer models.

Supported Models

  • SmolLM (135M, 360M parameters)
  • Qwen 0.5B
  • Phi-2, Phi-3

Setup

  1. Convert your SLM to .sentis format.
  2. Create a UnityInferenceEngineProvider asset and set Mode to Chat.
  3. Configure OnDeviceLlmConfig with:
    • Vocab file (JSON): Tokenizer vocabulary file
    • Merges file (TXT): BPE merges file for tokenization
    • Tokenizer config file (JSON): Special tokens and tokenizer settings
    • Chat template format (string): Template for formatting prompts; use {0} for the user message and {1} for the system message
    • Max Tokens (int): Maximum tokens to generate (default: 100)
    • Max Prompt Length (int): Maximum prompt length in tokens (default: 512)
    • Architecture fields: Match maxLayers, numKeyValueHeads, headDim, and eosTokenId to the selected model.

Execution Modes

ModeSpeedFramerate ImpactUse Case
Blocking
1-5s
May freeze frames
Quick responses when occasional stutter is acceptable
NonBlocking
5-15s
Smooth
Real-time experiences requiring consistent framerate

Performance Tuning

  • Steps Per Frame: Control tokens generated per frame (50-300 range)
  • Max Tokens: Limit response length (default: 100)
  • Max Prompt Length: Prevent memory spikes (default: 512)

Example Usage

using System.Threading;
using System.Threading.Tasks;
using Meta.XR.BuildingBlocks.AIBlocks;
using UnityEngine;

public class ChatExample : MonoBehaviour
{
    [SerializeField] private UnityInferenceEngineProvider provider;

    async Task TestChat(CancellationToken cancellationToken = default)
    {
        try
        {
            var req = new ChatRequest("Hello, how are you?");
            var response = await provider.ChatAsync(req, ct: cancellationToken);
            Debug.Log(response.text);
        }
        catch (System.Exception ex)
        {
            Debug.LogError($"Chat failed: {ex.Message}");
        }
    }
}
See Agents and Building Blocks to learn how each AI building block works.