← Назад к вопросам

Как выгрузить объект из памяти, когда он перестал быть необходим, при использовании Addressables для загрузки?

2.3 Middle🔥 162 комментариев
#Управление памятью

Комментарии (2)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Управление памятью при работе с Addressables

При использовании Addressables System в Unity выгрузка объектов из памяти происходит иначе, чем при традиционном подходе с Resources.UnloadUnusedAssets(). Addressables предоставляет более контролируемый и предсказуемый механизм управления памятью, основанный на явном освобождении ссылок.

Ключевые механизмы выгрузки

Основные способы выгрузки объектов, загруженных через Addressables:

  1. Release Instance - для экземпляров игровых объектов
  2. Release Asset - для загруженных ассетов
  3. Auto-release через Reference Counting - автоматическое управление через подсчет ссылок

Практическая реализация

1. Выгрузка экземпляров GameObject

using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;

public class AddressableManager : MonoBehaviour
{
    private AsyncOperationHandle<GameObject> _handle;
    private GameObject _loadedObject;

    async void Start()
    {
        // Загрузка объекта
        _handle = Addressables.LoadAssetAsync<GameObject>("MyPrefab");
        _loadedObject = await _handle.Task;
        
        // Создание экземпляра
        GameObject instance = Instantiate(_loadedObject);
        
        // Когда объект больше не нужен
        Destroy(instance);
        
        // Важно: освобождаем handle, а не только уничтожаем GameObject
        Addressables.Release(_handle);
    }
}

2. Работа с Reference Counting

Addressables использует систему подсчета ссылок. Каждый вызов LoadAssetAsync увеличивает счетчик, а Release - уменьшает. Объект выгружается, когда счетчик достигает нуля.

public class AssetLoader : MonoBehaviour
{
    private List<AsyncOperationHandle> _handles = new List<AsyncOperationHandle>();

    public async void LoadAndReleaseMultiple()
    {
        // Загрузка нескольких ассетов
        var handle1 = Addressables.LoadAssetAsync<Texture>("Texture1");
        var handle2 = Addressables.LoadAssetAsync<Material>("Material1");
        
        _handles.Add(handle1);
        _handles.Add(handle2);

        await Task.WhenAll(handle1.Task, handle2.Task);

        // Использование ассетов...
        
        // Выгрузка всех ассетов
        foreach (var handle in _handles)
        {
            Addressables.Release(handle);
        }
        _handles.Clear();
    }
}

3. Автоматическое управление через using-паттерн

public async Task<TemporaryAssetUsage> TemporaryLoadAsset()
{
    var handle = Addressables.LoadAssetAsync<GameObject>("TemporaryAsset");
    await handle.Task;
    
    // Используем using для автоматического освобождения
    return new TemporaryAssetUsage(handle);
}

public class TemporaryAssetUsage : System.IDisposable
{
    private AsyncOperationHandle<GameObject> _handle;

    public TemporaryAssetUsage(AsyncOperationHandle<GameObject> handle)
    {
        _handle = handle;
    }

    public void Dispose()
    {
        Addressables.Release(_handle);
    }
}

Важные аспекты и рекомендации

Проблемы и решения:

  • Утечки памяти: Часто возникают, когда разработчики забывают вызвать Release(). Всегда отслеживайте ваши handles

  • Статистика и мониторинг:

// Проверка использования Addressables
Debug.Log($"Total Handles: {Addressables.ResourceManager.ActiveHandlesCount}");
  • Категории выгрузки:
    • Manual Release: Полный контроль, но требует внимательности
    • Scene-based Release: Автоматическая выгрузка при смене сцены
    • Time-based Release: Выгрузка через определенное время неактивности

Оптимизация стратегий:

  1. Группировка ресурсов: Объединяйте связанные ассеты в один AssetBundle для одновременной загрузки/выгрузки

  2. Приоритеты выгрузки: Критичные ресурсы оставляйте в памяти, временные - быстро выгружайте

  3. Профилирование: Используйте Addressables Event Viewer и Memory Profiler для отслеживания использования

Распространенные ошибки

  1. Двойное освобождение: Вызов Release() несколько раз для одного handle
  2. Несоответствие типов: Загрузка одного типа, а освобождение другого
  3. Утечка в корутинах: Незавершенные асинхронные операции, которые сохраняют ссылки

Передовые практики

  • Всегда используйте await/async вместо callback-ов для лучшей читаемости
  • Создайте фасад или менеджер для централизованного управления Addressables
  • Реализуйте паттерн Object Pool для часто используемых объектов
  • Используйте Addressables Analyze Tool для проверки целостности ссылок

Addressables System обеспечивает мощный механизм управления памятью, но требует дисциплинированного подхода к освобождению ресурсов. Ключевой принцип: "что явно загружено через Addressables, должно быть явно освобождено через Release()".