🧠 Утечки памяти в Unity 🧠

Ещё один полезный доклад с Unite 2025: How to find memory leaks with the Memory Profiler.

Несмотря на название, в докладе внимание уделено не только возможностям Memory Profiler.

Есть информация и про типы памяти: Native, Managed, Graphics, Untracked.

Есть про естественный рост потребления, про утечки памяти, про фрагментацию и её особенности с GC в Unity (т.е. про Boehm и CoreCLR).

В некотором смысле, он хорошо дополняет доклад Understanding Unity memory.

——————————

Основные причины утечек

• Частые аллокации. • Как следствие, фрагментация памяти. • Удержание ссылок на данные дольше, чем это необходимо, что мешает работе GC. • В частности, создание/загрузка ассетов без их последующего уничтожения.

——————————

Что к этому приводит

• Отсутствие своевременной очистки статических ссылок на объекты и коллекции.

• Отсутствие отписок для событий и делегатов.

• Использование анонимных функций и лямбда-выражений для подписки: ими невозможно отписаться без костылей и пристроек. И они могут вызывать при этом замыкание (про замыкание).

• Отсутствие вызова Dispose у того, что это требует.

• Неявное клонирование материалов: при обращении к .material может создаваться новый материал, который нужно уничтожать (нужно помнить про .sharedMaterial).

• Злоупотребление асинхронными методами без CancellationToken или в Forget-режиме: могут работать неконтролируемо долго и удерживать ссылки на данные.

——————————

Как этого избежать

• Сделал подписку — тут же задизайнил отписку. Сразу, не откладывая. Это и надёжнее (не забудешь), и получится архитектурно чище, т.к. придётся сразу продумать жизненный цикл реализуемой фичи.

• Аналогично для Dispose.

• Использовать симметрию: делать обратные действия в противоположных фазах. Это удобно дополняет прошлые пункты и упрощает контроль.

Например, в OnEnable — подписались, в OnDisable — отписались. В Start — инициализировали, в OnDestroy — деинициализировали. И т.д.

• Отказ от анонимных функций и лямбд для подписок: предпочитать методы.

• Избегать хранения данных в статике. Только в случаях реальной необходимости или соответствия дизайну приложения.

• Внимательно следить за статическими данными. И своевременно удалять оттуда неактуальные данные.

• Выгружать загруженные или созданные ранее ассеты, при потере необходимости в них.

• Использовать CancellationToken и/или принудительные таймауты для асинхронных методов.

• Использовать пул объектов вместо частого создания и уничтожения одних и тех же объектов для снижения фрагментации.

——————————

Ещё у меня есть короткие тематические нарезки из старых докладов: • Про фрагментациюПро пул объектов

🧠 Утечки памяти в Unity 🧠 | Сетка — социальная сеть от hh.ru