Danil Iarosh 839a68aef1 Improve VFX, UI overlays, session statistics, COM reliability, audio mixer, and expand architecture guides
Подробный список изменений:
- Перенесены эффекты частиц из C#-кода в готовые префабы-ассеты (Vfx Prefabs) в папке Assets/Resources/Vfx/ с автоматической генерацией материалов в Editor.
- Исправлены ошибки duration на играющих системах частиц и розовые текстуры в GameVfxService.cs.
- Исправлена навигация и фокус кнопок на оверлеях ContinueGameOverlay и PrizeResultOverlay с автоматическим подсвечиванием кнопок лимонно-зеленым цветом при фокусе и проигрыванием звука.
- Добавлена проверка настроек в GameplayHudController.cs для скрытия ContinueGameOverlay, если продолжение игры отключено.
- Расширен сбор статистики: создана структура GameplaySessionRecord, добавлена история до 50 раундов в PrizeSessionStateService и JsonPrizeSessionStateRepository, выведен расчет средних показателей и список 5 последних раундов в сервисной статистике.
- Повышена надежность COM-транспорта: добавлен sleep (80мс) в Dispose для graceful shutdown потоков, реализован цикл переподключения до 10 попыток при обрыве связи.
- Интегрированы настройки громкости с микшером: изменен шаг изменения громкости на 5% (0.05) для удобства, добавлен статус-чек и логи в ApplyServiceVolumes, расширены юнит-тесты на GetFloat параметры.
- Созданы новые архитектурные гайды по аппаратному COM-транспорту и призовой экономике автомата в папке GUIDES/architecture/.
- Оптимизирован и обновлен RAG-индекс проекта.
2026-07-03 15:04:08 +03:00

97 lines
4.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Полное руководство по Addressables
Система **Addressables** (`com.unity.addressables`) — это замена устаревшей папке `Resources` и сложным `AssetBundles`. Она позволяет загружать контент по текстовому адресу из любой точки (локально или с удаленного сервера), не меняя код игры.
## 1. Загрузка одиночных ассетов и Интеграция с UniTask
В проекте мы используем `Cysharp.Threading.Tasks` для превращения неудобных `AsyncOperationHandle` в удобные `UniTask`.
```csharp
using UnityEngine.AddressableAssets;
using Cysharp.Threading.Tasks;
using UnityEngine;
public class AssetLoader
{
public async UniTask<GameObject> LoadPlayerPrefabAsync()
{
// "PlayerPrefab" — это адрес, заданный в окне Addressables Groups
GameObject prefab = await Addressables.LoadAssetAsync<GameObject>("PlayerPrefab").ToUniTask();
return prefab;
}
}
```
## 2. Инстанцирование (InstantiateAsync)
Если вам нужно загрузить префаб и сразу создать его на сцене, **НЕ ИСПОЛЬЗУЙТЕ** `Object.Instantiate(await LoadAssetAsync())`.
Правильный способ — использовать `Addressables.InstantiateAsync`.
```csharp
public async UniTask<GameObject> SpawnEnemyAsync(Vector3 position)
{
// Загрузит префаб в память и сразу создаст его копию на сцене.
// Addressables сам отслеживает этот объект!
GameObject enemyInstance = await Addressables.InstantiateAsync("EnemyPrefab", position, Quaternion.identity).ToUniTask();
return enemyInstance;
}
```
## 3. Reference Counting и Управление Памятью (КРИТИЧНО)
Главная проблема Addressables — утечки памяти (Memory Leaks), если не освобождать ресурсы. Система использует счетчик ссылок (Reference Counting).
- Загрузили текстуру — счетчик = 1.
- Загрузили ее еще раз где-то еще — счетчик = 2.
- Вызвали `Release` — счетчик = 1.
- Вызвали `Release` еще раз — счетчик = 0, текстура выгружена из оперативной памяти (RAM/VRAM).
### Правила освобождения памяти:
**Сценарий 1: Вы использовали `LoadAssetAsync`**
Если вы загрузили ассет (например, `ScriptableObject` настроек, AudioClip или Texture), вы обязаны вызвать `Addressables.Release()`.
```csharp
private AudioClip backgroundMusic;
public async UniTask PlayMusicAsync()
{
backgroundMusic = await Addressables.LoadAssetAsync<AudioClip>("MenuMusic").ToUniTask();
audioSource.PlayOneShot(backgroundMusic);
}
public void OnDestroy()
{
// Если объект уничтожается, освобождаем память от музыки!
if (backgroundMusic != null)
{
Addressables.Release(backgroundMusic);
}
}
```
**Сценарий 2: Вы использовали `InstantiateAsync`**
Если вы создали GameObject через Addressables, вы **не должны** удалять его через `Destroy(gameObject)`. Используйте `Addressables.ReleaseInstance()`.
```csharp
public void KillEnemy(GameObject enemyInstance)
{
// Это автоматически уничтожит GameObject на сцене И уменьшит счетчик префаба в памяти.
// Если это был последний враг такого типа, сам префаб выгрузится из RAM.
Addressables.ReleaseInstance(enemyInstance);
}
```
## 4. Загрузка по Меткам (Labels)
Addressables позволяет загружать списки ассетов. Например, вы можете пометить все префабы уровней меткой `Level` и загрузить их одним вызовом.
```csharp
public async UniTask<IList<LevelData>> LoadAllLevelsAsync()
{
// Загружает все ассеты, у которых стоит Label "Level"
IList<LevelData> levels = await Addressables.LoadAssetsAsync<LevelData>("Level", null).ToUniTask();
return levels;
}
```