Danro-Jump/GUIDES/applied_usage/Zenject_UniTask_Init.md
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

148 lines
5.9 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.

# Комбинированный пример: Zenject + UniTask + Addressables для старта игры
В современных проектах старт игры — это не просто `SceneManager.LoadScene()`. Это цепочка асинхронных операций: проверка обновлений, загрузка баз данных (баланс, цены), авторизация, инициализация железа (как в Danro Jump) и только затем показ меню.
Этот гайд показывает, как объединить 3 главные библиотеки проекта в одну элегантную систему загрузки.
## 1. Интерфейс Загрузочной Задачи (Task)
Для начала, сделаем систему расширяемой. Вместо жестко закодированных вызовов, создадим интерфейс `IStartupTask`.
```csharp
using Cysharp.Threading.Tasks;
public interface IStartupTask
{
// Вес задачи для прогресс-бара (например, 10%)
float ProgressWeight { get; }
// Выполнение задачи с возможностью отмены
UniTask ExecuteAsync(System.Threading.CancellationToken ct);
}
```
## 2. Реализация задач (Примеры)
### Задача 1: Загрузка конфигураций (Addressables)
```csharp
using UnityEngine.AddressableAssets;
public class LoadConfigTask : IStartupTask
{
public float ProgressWeight => 30f;
private readonly ConfigManager configManager;
// Внедряем зависимость!
public LoadConfigTask(ConfigManager configManager) => this.configManager = configManager;
public async UniTask ExecuteAsync(System.Threading.CancellationToken ct)
{
// Загружаем глобальные настройки из Addressables
var config = await Addressables.LoadAssetAsync<GameConfig>("GlobalConfig")
.WithCancellation(ct); // Привязываем токен отмены
configManager.Initialize(config);
}
}
```
### Задача 2: Подключение оборудования (COM-порт / UniTask)
```csharp
public class HardwareInitTask : IStartupTask
{
public float ProgressWeight => 40f;
private readonly ComSystem comSystem;
public HardwareInitTask(ComSystem comSystem) => this.comSystem = comSystem;
public async UniTask ExecuteAsync(System.Threading.CancellationToken ct)
{
// Инициализация железа с таймаутом в 5 секунд!
try
{
await comSystem.InitializeHardwareAsync().Timeout(System.TimeSpan.FromSeconds(5));
}
catch (System.TimeoutException)
{
UnityEngine.Debug.LogError("Железо не ответило вовремя!");
// Показать ошибку на экране
}
}
}
```
## 3. Регистрация задач в Zenject (Installer)
В `BootstrapInstaller` (привязанном к первой пустой сцене) мы регистрируем все наши задачи.
```csharp
public class BootstrapInstaller : MonoInstaller
{
public override void InstallBindings()
{
// Биндим сам менеджер загрузки
Container.BindInterfacesAndSelfTo<AppBootstrapper>().AsSingle();
// Биндим задачи как список. Zenject соберет их все в один List<IStartupTask>
Container.Bind<IStartupTask>().To<LoadConfigTask>().AsCached();
Container.Bind<IStartupTask>().To<HardwareInitTask>().AsCached();
}
}
```
## 4. Исполнитель (AppBootstrapper)
Этот класс запустится автоматически благодаря интерфейсу `IInitializable`.
```csharp
using System.Collections.Generic;
using Zenject;
using Cysharp.Threading.Tasks;
public class AppBootstrapper : IInitializable, System.IDisposable
{
private readonly List<IStartupTask> tasks;
private readonly ISceneFlowService sceneFlow;
private System.Threading.CancellationTokenSource cts;
// Zenject автоматически передаст все классы, которые мы привязали к IStartupTask
public AppBootstrapper(List<IStartupTask> tasks, ISceneFlowService sceneFlow)
{
this.tasks = tasks;
this.sceneFlow = sceneFlow;
}
public void Initialize()
{
cts = new System.Threading.CancellationTokenSource();
RunStartupFlowAsync(cts.Token).Forget();
}
private async UniTaskVoid RunStartupFlowAsync(System.Threading.CancellationToken ct)
{
float totalProgress = 0f;
foreach (var task in tasks)
{
// Выполняем задачу последовательно
await task.ExecuteAsync(ct);
// Здесь можно вызывать сигнал для обновления UI прогресс-бара
totalProgress += task.ProgressWeight;
UnityEngine.Debug.Log($"Progress: {totalProgress}%");
}
// 4. Когда все задачи выполнены — переходим в меню!
sceneFlow.OpenMainMenu();
}
public void Dispose()
{
cts?.Cancel();
cts?.Dispose();
}
}
```
**Итог**: Мы получили масштабируемую, потокобезопасную (в рамках UniTask) и легко тестируемую систему инициализации. Чтобы добавить новую логику (например, проверку лицензии), нужно просто создать новый класс `IStartupTask` и забиндить его в инсталлере в 1 строчку кода! Никаких гигантских God-объектов.