HVoid
Полная документация
Введение
HVoid - это профессиональный инструмент для управления асинхронными операциями в Unity. Он позволяет легко:
Выполнять задачи в фоновых потоках
Работать с главным потоком Unity
Отменять операции
Отслеживать прогресс задач
Запускать корутины из любого потока
Преимущества HVoid:
Простота использования (минимальный порог входа)
Высокая производительность
Безопасная работа с потоками
Интеграция с жизненным циклом Unity
Установка
Поместите его в папку
Assets/PluginsГотово! Система автоматически инициализируется
Быстрый старт
Пример 1: Простая фоновая задача
using HVoid;
using UnityEngine;
public class SimpleExample : MonoBehaviour
{
    void Start()
    {
        // Запускаем метод в фоновом потоке
        HVoid.Background(ProcessData);
    }
    void ProcessData()
    {
        Debug.Log("Начали обработку в фоне...");
        
        // Имитируем долгую операцию
        System.Threading.Thread.Sleep(3000);
        
        // Возвращаемся в главный поток
        HVoid.Main(() => {
            Debug.Log("Обработка завершена!");
        });
    }
}Основные функции
1. Работа с главным потоком
HVoid.Main()
Выполняет код в главном потоке Unity. Обязательно используйте для работы с Unity API.
// Обновляем UI из любого потока
HVoid.Main(() => {
    scoreText.text = "Очки: 100";
    player.transform.position = Vector3.zero;
});
// Группируем несколько операций
HVoid.Main(() => {
    EnablePlayerControls();
    UpdateHealthBar();
    PlaySoundEffect();
});HVoid.MainAsync()
Выполняет код в главном потоке и возвращает Task для ожидания.
async void LoadGameAssets()
{
    // Показываем загрузочный экран
    await HVoid.MainAsync(() => {
        ShowLoadingScreen();
        DisableInput();
    });
    
    // Загружаем данные в фоне
    await HVoid.Background(LoadAssets);
    
    // Скрываем загрузочный экран
    await HVoid.MainAsync(HideLoadingScreen);
}2. Фоновые задачи
HVoid.Background()
Запускает метод в фоновом потоке.
// Простой запуск
HVoid.Background(CalculateStatistics);
// С лямбда-выражением
HVoid.Background(() => {
    var result = ComplexCalculation();
    HVoid.Main(() => DisplayResult(result));
});
// С параметрами
void StartProcessing(string data)
{
    HVoid.Background(() => ProcessData(data));
}HVoid.Background() с прогрессом
// Создаем обработчик прогресса
var progress = new Progress<float>(p => {
    loadingBar.fillAmount = p;
    percentText.text = $"{p:P0}";
});
// Запускаем задачу с прогрессом
HVoid.Background(ct => {
    for (int i = 0; i <= 100; i++)
    {
        // Проверяем отмену
        ct.ThrowIfCancellationRequested();
        
        // Имитируем работу
        System.Threading.Thread.Sleep(50);
        
        // Отправляем прогресс
        progress.Report(i / 100f);
    }
}, progress);3. Отменяемые задачи
HVoid.CancellableBackground()
Создает задачу, которую можно отменить.
CancellationTokenSource cts;
void StartLongOperation()
{
    // Запускаем задачу с возможностью отмены
    (var task, cts) = HVoid.CancellableBackground(ct => {
        while (true)
        {
            ct.ThrowIfCancellationRequested();
            // Выполняем работу...
        }
    });
}
void CancelOperation()
{
    // Отменяем операцию
    cts?.Cancel();
}4. Отложенные действия
HVoid.Delayed()
Выполняет действие через указанное время.
// Простая задержка
HVoid.Delayed(2.5f, () => {
    ShowTutorialMessage();
});
// С проверкой существования объекта
HVoid.Delayed(5f, () => {
    if (this != null) // Проверяем, что объект существует
    {
        Destroy(gameObject);
    }
});Продвинутые сценарии
Пример: Загрузка данных с сервера
async void LoadPlayerProfile()
{
    try
    {
        // Показываем индикатор загрузки
        HVoid.Main(() => loadingIndicator.SetActive(true));
        
        // Загружаем данные в фоне
        var profile = await HVoid.Background(() => {
            return ServerApi.GetPlayerProfile(playerId);
        });
        
        // Обновляем UI
        HVoid.Main(() => {
            playerName.text = profile.name;
            playerAvatar.sprite = LoadAvatar(profile.avatarId);
        });
    }
    catch (Exception ex)
    {
        Debug.LogError($"Ошибка загрузки: {ex.Message}");
        HVoid.Main(() => ShowErrorPopup("Не удалось загрузить данные"));
    }
    finally
    {
        HVoid.Main(() => loadingIndicator.SetActive(false));
    }
}Пример: Параллельная обработка
async void ProcessAllData()
{
    // Создаем задачи
    var textureTask = HVoid.Background(() => ProcessTextures());
    var audioTask = HVoid.Background(() => ProcessAudio());
    var modelTask = HVoid.Background(() => ProcessModels());
    
    // Ждем завершения всех задач
    await Task.WhenAll(textureTask, audioTask, modelTask);
    
    // Уведомляем о завершении
    HVoid.Main(() => Debug.Log("Все ресурсы обработаны!"));
}Пример: Генерация мира
async void GenerateWorld()
{
    var progress = new Progress<GenerationStage>(stage => {
        HVoid.Main(() => UpdateGenerationProgress(stage));
    });
    
    await HVoid.Background(ct => {
        GenerateTerrain(ct, progress);
        GenerateVegetation(ct, progress);
        GenerateStructures(ct, progress);
    }, progress);
}Лучшие практики
1. Всегда проверяйте отмену в длительных операциях
HVoid.Background(ct => {
    for (int i = 0; i < 1000000; i++)
    {
        // Регулярно проверяем токен отмены
        ct.ThrowIfCancellationRequested();
        
        // Выполняем работу...
    }
});2. Минимизируйте вызовы главного потока
Когда что выбирать?
Используйте
HVoid.Main()когда:Нужно просто выполнить действие на главном потоке
Не важно, когда именно выполнится операция
Делаете единичные простые операции
Используйте
HVoid.MainAsync()когда:Нужно дождаться завершения операции
Работаете с async/await
Строите цепочки последовательных операций
Требуется гарантия выполнения перед продолжением кода
Производительность
Main()немного эффективнее для единичных операцийДля групповых операций лучше использовать один вызов
MainAsync()вместо несколькихMain()
// Плохо: много отдельных вызовов
for (int i = 0; i < 1000; i++)
{
    HVoid.Main(() => UpdateItem(i));
}
// Хорошо: один вызов для всех операций
HVoid.Main(() => {
    for (int i = 0; i < 1000; i++)
    {
        UpdateItem(i);
    }
});
// Оптимально
await HVoid.MainAsync(() => {
    for (int i = 0; i < 1000; i++)
    {
        UpdateItem(i);
    }
});3. Используйте async/await для цепочек задач
async void LoadGame()
{
    await LoadConfig();
    await LoadAssets();
    await InitializeSystems();
    StartGame();
}Часто задаваемые вопросы
В: Безопасно ли использовать Unity API в фоновом потоке?
О: Нет! Все операции с Unity API должны выполняться через:
HVoid.Main()HVoid.MainAsync()HVoid.MainCoroutine()
В: Как обрабатывать ошибки в фоновых задачах?
csharpCopyDownload
try
{
    await HVoid.Background(() => {
        throw new InvalidOperationException("Тестовая ошибка");
    });
}
catch (Exception ex)
{
    Debug.LogError($"Перехвачено исключение: {ex.Message}");
    HVoid.Main(() => ShowError(ex.Message));
}В: Как отменить все задачи при выходе из игры?
О: HVoid автоматически отменяет все задачи при завершении работы приложения.
Заключение
HVoid предоставляет мощные и простые инструменты для работы с асинхронным кодом в Unity. С его помощью вы можете:
Упростить сложную многопоточную логику
Улучшить производительность вашей игры
Создавать плавные и отзывчивые интерфейсы
Легко управлять длительными операциями
Реализовывать сложные сценарии загрузки
Для новичков рекомендуется начать с простых примеров из раздела "Быстрый старт", постепенно переходя к более сложным сценариям.
Last updated
Was this helpful?