Асинхронное программирование

Для реализации сценариев с асинхронным поведением — таких как последовательные анимации, задержки, ожидание условий или неблокирующее выполнение логики — платформа Varwin предоставляет встроенную поддержку корутин на основе синтаксиса async/await.

В отличие от стандартной библиотеки asyncio, асинхронная модель Varwin интегрирована напрямую с игровым циклом движка и гарантирует, что весь пользовательский код выполняется в основном потоке, где доступны все объекты сцены и их методы.

Класс Varwin.Async

Основной точкой входа для работы с корутинами является класс Varwin.Async. Он предоставляет методы для регистрации и запуска асинхронных функций в контексте жизненного цикла сцены.

Основные методы:

  • Varwin.Async.Run(coro) — немедленно запускает переданную корутину.

  • Varwin.Async.AddStart(coro_func) — регистрирует асинхронную функцию (не результат вызова!), которая будет запущена один раз при старте сцены.

  • Varwin.Async.AddUpdate(coro_func) — регистрирует асинхронную функцию, вызываемую зацикленно (аналогично Update в Unity, но с поддержкой await).

Пример использования:

async def Chain2():
    # Масштабируем объект в течение 1 секунды
    await cube10.ScaleBehaviour.ScaleOverTime(Varwin.Vector3(7, 1, 1), 1)
    # Ждём 2 секунды
    await Varwin.WaitForSeconds(2)
    # Возвращаем исходный масштаб
    await cube10.ScaleBehaviour.ScaleOverTime(Varwin.Vector3(1, 1, 1), 1)

# Запуск корутины
Varwin.Async.Run(Chain2())

Обратите внимание: при использовании AddStart и AddUpdate передаётся сама функция, а не её вызов:

Varwin.Async.AddStart(Chain2)  # ✅ правильно
# Varwin.Async.AddStart(Chain2())  # ❌ ошибка: функция уже вызвана

Встроенные await-объекты

Для организации задержек и синхронизации с игровым циклом Varwin предоставляет специальные awaitable-объекты. Они приостанавливают выполнение корутины до наступления определённого события.

Доступные типы:

  • WaitForSeconds — приостанавливает выполнение на заданное количество секунд.

  • WaitForEndOfFrame — приостанавливает выполнение до конца текущего кадра.

  • WaitWhile — приостанавливает выполнение, пока заданное условие (callable) возвращает True.

Пример с WaitWhile:

async def WaitCubeMoving():
    await Varwin.WaitWhile(lambda: cube.MotionBehaviour.Position.X < 5.0)
    Varwin.Debug.Log("Куб достиг позиции X=5!")

Предупреждение

Не используйте стандартную библиотеку asyncio для взаимодействия с объектами сцены. Все компоненты движка (включая трансформации, поведения, события) доступны только в основном потоке, в то время как asyncio может выполнять код в фоновых потоках или событийных циклах, не связанных с игровым циклом. Это приведёт к ошибкам или неопределённому поведению.

Рекомендации

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

  • Избегайте блокирующих вызовов (например, time.sleep()) — они остановят весь движок.

  • Всегда предпочитайте await Varwin.WaitForSeconds(...) вместо синхронных задержек.

  • Для параллельного выполнения нескольких задач запускайте несколько корутин через Varwin.Async.Run().

Корутины в Varwin — это безопасный и удобный способ писать читаемую, последовательную логику без явного управления состояниями или таймерами.