~3 мин чтения

Sentis — ML inference в Unity

ONNX-модели в реальном времени, IWorker, практический пример классификации изображения.

Sentis — встроенная в Unity 6 система для выполнения машинного обучения в реальном времени внутри игры. Заменил Barracuda (deprecated с 2023).

Что можно с Sentis:

  • Классификация изображений с камеры (ResNet, MobileNet, YOLO).
  • NPC AI на нейросетях (decision-making, dialog generation).
  • Style transfer для post-process эффектов.
  • Pose estimation для motion capture без датчиков.
  • Voice command recognition.

Установка и базовая идея

  1. Package Manager → установите Sentis (com.unity.sentis). С Unity 6.1 — официально GA.
  2. Импортируйте .onnx-файл (ONNX — открытый формат экспорта моделей из PyTorch, TensorFlow и др.) как обычный ассет. Unity автоматически распознаёт и конвертирует.
  3. В коде используете ModelLoader.Load(modelAsset)Workerworker.Schedule(input)worker.PeekOutput().
Веб

transformers.js от Hugging Face — запуск моделей в браузере через ONNX Runtime Web. Sentis — то же концептуально, но native через compute shaders, без WebAssembly overhead.

Unity

Sentis под капотом — GPU compute shaders (опционально CPU). Inference 60+ FPS для маленьких моделей на потребительском железе. Один Worker — один runtime для одной модели; создаёте на время загрузки.

Полный пример: классификация изображения

Возьмём MobileNetV2 — лёгкая модель, классифицирует картинку 224×224 в одну из 1000 категорий (ImageNet).

Подготовка

  1. Скачайте mobilenetv2.onnx (например, с ONNX Model Zoo).
  2. Перетащите в Assets/ — появится ModelAsset.
  3. Создайте labels.txt со 1000 строк-категорий (классы ImageNet).

Скрипт

using System.Collections.Generic;
using System.Linq;
using Unity.Sentis;
using UnityEngine;

public class ImageClassifier : MonoBehaviour
{
    [SerializeField] private ModelAsset modelAsset;
    [SerializeField] private TextAsset labels;        // labels.txt
    [SerializeField] private Camera sourceCamera;
    [SerializeField] private RenderTexture cameraOutput;

    private Worker _worker;
    private Model _model;
    private string[] _classes;

    private void Awake() {
        _model = ModelLoader.Load(modelAsset);
        _worker = new Worker(_model, BackendType.GPUCompute);
        _classes = labels.text.Split('\n').Select(s => s.Trim()).ToArray();
    }

    private void OnDestroy() {
        _worker?.Dispose();
    }

    public void Classify() {
        // 1. Преобразуем картинку (RenderTexture) → Tensor 1×3×224×224 (NCHW)
        using var input = TextureConverter.ToTensor(cameraOutput, width: 224, height: 224, channels: 3);

        // 2. Запускаем модель
        _worker.Schedule(input);

        // 3. Читаем output (1×1000 — confidence для каждого класса)
        using var output = (_worker.PeekOutput() as Tensor<float>).ReadbackAndClone();

        // 4. Находим argmax
        int bestIdx = 0;
        float bestVal = output[0];
        for (int i = 1; i < output.shape[1]; i++) {
            if (output[0, i] > bestVal) {
                bestVal = output[0, i];
                bestIdx = i;
            }
        }

        Debug.Log($"Detected: {_classes[bestIdx]} (confidence: {bestVal:F3})");
    }

    private void Update() {
        if (Input.GetKeyDown(KeyCode.Space)) {
            Classify();
        }
    }
}

При нажатии Space скрипт берёт картинку с камеры (cameraOutput — RenderTexture, в которую sourceCamera рендерит), прогоняет через модель и выводит наиболее вероятный класс.

Backend selection — GPU vs CPU

Worker принимает BackendType:

BackendКогда
BackendType.GPUComputeDefault. Compute shaders, быстро на современных GPU.
BackendType.GPUPixelFallback для GPU без compute shader (старый WebGL).
BackendType.CPUКогда нет GPU или нужен deterministic output (для replay-системы).

Производительность для MobileNetV2 224×224 на NVIDIA GTX 1060:

  • GPUCompute: ~5 мс
  • CPU: ~50 мс

Tensor — input/output формат

Sentis работает с типом Tensor<float> (или Tensor<int>). У него есть shape — массив размерностей. Для NCHW (стандартный image format):

  • N = batch size (обычно 1 для real-time)
  • C = каналы (3 для RGB)
  • H, W = высота × ширина
// Создать тензор из массива
var tensor = new Tensor<float>(new TensorShape(1, 3, 224, 224));
for (int i = 0; i < tensor.count; i++) {
    tensor[i] = Random.value;
}

// Или из Texture / RenderTexture
var tex = TextureConverter.ToTensor(rt);

Важно: Tensor реализует IDisposable. Если забыли .Dispose(), утечка GPU-памяти.

Использование в game logic

Распространённые паттерны:

NPC decision-making

NN модель принимает вектор “состояния игры” и возвращает action. Pre-trained reinforcement learning из ML-Agents → экспорт в ONNX → импорт в shipping-build.

Style transfer на видео

Применить художественный стиль (e.g., Ghibli, oil painting) к рендеру камеры в реальном времени. Sentis запускает StyleGAN-подобную модель на каждый кадр.

Speech-to-text

Whisper или подобная модель → конвертация микрофонного ввода в текст для voice commands.

Image-based AI

Захват изображения с камеры (AR-режим) → определение объектов через YOLO → размещение виртуальных объектов рядом с реальными.

Performance budget важен

Большие модели (несколько сотен МБ) inference часто стоит >16.6 мс на кадр — игра тормозит. Решения:

  • Использовать меньшую модель (MobileNet вместо ResNet).
  • Запускать раз в N кадров, а не каждый — для NPC decision-making достаточно 5 FPS.
  • Quantize модель до int8 (если ML-фреймворк поддерживает).
  • Async inference через worker.ScheduleAsync (возвращает Promise-like).

Async inference

public async Awaitable ClassifyAsync(RenderTexture input) {
    using var tensor = TextureConverter.ToTensor(input, 224, 224, 3);

    _worker.Schedule(tensor);
    // Ждём, пока GPU закончит — не блокируем main thread
    using var output = (_worker.PeekOutput() as Tensor<float>);
    await output.ReadbackRequestAsync();

    using var cpu = output.ReadbackAndClone();
    // Обрабатываем результат
}

ReadbackRequestAsync ждёт асинхронно без главного потока — игра продолжает рендериться.

Где брать модели

  • ONNX Model Zoo — официальный репо с готовыми моделями (classification, detection, NLP).
  • Hugging Face — гигантская библиотека. Часто поставляются с PyTorch — экспортируете в ONNX через torch.onnx.export().
  • Unity AI Hub — Unity collection моделей, оптимизированных для Sentis.
  • Custom training: тренируете в PyTorch/TensorFlow → экспорт в ONNX → импорт в Unity.

Ограничения Sentis

  • Не все операторы поддержаны — некоторые экзотические слои (custom CUDA-операции) не работают.
  • Dynamic shapes ограничены — Sentis предпочитает fixed input size (хорошо для большинства game ML-моделей).
  • Memory footprint — большие модели жрут VRAM. Профайлите.
  • WebGL — работает, но медленно (GPU compute shaders в браузере = WebGPU only).

Сравнение с альтернативами

SentisML-AgentsTorchSharp
НазначениеProduction inferenceTraining agentsGeneral .NET ML
BackendGPU compute / CPUPyTorch (training)LibTorch native
РазмерLightHeavyHeavy
Integration с UnityNativeNativeManual

ML-Agents используют для тренировки RL-агентов, Sentis — для запуска результирующей модели. Это разные фазы пайплайна.