Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

14 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

VICONTAMP RESEARCH

Общее

Этот проект показывает различные приёмы для разработки с использованием подходов "инверсии управления" и "шин сообщения".

Дополнительно показана замена стандартных Unity корутин более легкими конструктами для асинхронных процессов - "async-await". Асинхронные процессы через "async-await" стали доступны после внедрения их в C# и обновления поддерживаемой версии .Net в Unity.

Отдельно показано внедрение парсера, основанного на генераторе из грамматик - "Обобщённый восходящий магазинный анализатор" (GLR). Для простоты был внедрен парсер арифметических выражений со скобками с использованием простого стекового вычисления.

В проекте используются следующие сборки:

"Hime parser generator" не умеет генерировать пока напрямую в Unity и требует доработки. Для внедрения в Unity в готовый код парсера были внесены соответствующие небольшие изменения, которые потеряются при регенерации.

В проекте показаны не "дистиллированные" подходы, а те, которые предполагают, что проект уже существовал и в него стали внедрять новые модули.

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

Ко многим классам и их методам даны пояснения в виде комментариев.

В коде есть простые классы и наследники MonoBehaviour. И смысл внедрения новых модулей сводится к тому, что нужно разделить взаимодействие строго на два уровня:

  • Представление (UI, Renders, GameObject transforms) - реализуется полностью под управлением Unity
  • Логика и данные (Calculations, AI Behaviour, Save-Restore) - реализуется полностью без использования Unity

Для взаимодействия двух уровней используются строго определенные входы-выходы без прямого перебрасывания ссылок на объекты Unity на уровень логики.

На каждом уровне можно разделять на небольшие модули представления и логику с данными, чтобы упростить параллельную разработку и тестирование. Такой подход позволит также уменьшить сложность тестирования и при этот проводить тестирование на каждом уровне отдельно. Дополнительно предлагается любые зависимости прокидывать не напрямую, а через интерфейсы, что позволит не привязываться к Unity и другим специфичным модулям, а в Unity не придётся тянуть для тестов всю реализацию классов, можно будет "замокать пустышками" всё, что не нужно для проверки функционала.

Debug.Log(...) используется везде для упрощения кода и поэтому приходится везде использовать using UnityEngine;. В корректно построенной системе логгер внедряется как зависимость и поэтому нет необходимости привязываться к Unity в обычных классах.

Порядок изучения

Сформированы две сцены - одна основная (MainScene), другая дополнительная (SampleScene). В сцены добавлены игровые объекты, стандартные для любого Unity проекта. А также добавлены "менеджеры", которые обычно добавляют в игру для глобального доступа.

Дополнительно в сцены добавлены игровые объекты с единственной компонентой, унаследованной от "LifetimeScope", которая унаследована сама от MonoBehaviour и реализует интерфейс IDisposable, чтобы для "дерева" экземпляров и областей видимости вызывать "обработчик удаления" (Dispose). Эти объекты единственные, которые нужно добавить для внедрения новых подходов. Они определяют "жизненный цикл" и область видимости внедряемых экземпляров через DI. Отдельные области видимости могут быть определены и для "сложносоставного" префаба, что облегчит реализацию модульности с использованием бандлов, но более простым подходом является определение областей видимости только на уровне сцен и включения всех модулей в основную сборку (даже для DLC), а ассетами являются только графические, звуковые и конфигурационные ресурсы.

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

Для внедрения зависимостей в экземпляры простых классов через их конструкторы достаточно зарегистрировать все классы, интерфейсы через Register интерфейса IContainerBuilder.

Для внедрения зависимостей в экземпляры MonoBehaviour-наследников необходимо использовать в различных случаях следующие варианты:

  • Специальные методы регистрации (например, RegisterComponentOnNewGameObject), которые позволят создать игровой объект, которого нет на сцене. Так можно не нагружать лишними требованиями к настройке сцены.
  • Добавить существующие на сцене объекты в список для регистрации LifetimeScope компоненты у соответствующего игрового объекта. Так можно проверять связанность системы после изменений в сцене.

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

Хорошей практикой является определение класса родительской LifetimeScope компоненты в дополнительной сцене для её LifetimeScope объекта, но это так же можно сделать через EnqueueParent.

В логику "игры" внедрены ограничения, которые отключают кнопку загрузки дополнительных сцен, если не выгружены все текущие дополнительные сцены. Но так как загрузка дополнительной сцены идёт с искусственным запаздыванием на 3 секунды, то можно успеть нажать несколько раз на кнопку загрузки дополнительных сцен. При нескольких нажатиях на кнопку будет отправлено несколько событий-намерений и произойдёт загрузка нескольких дополнительных сцен, которые будут работать независимо друг от друга.

Можно изучать скрипты в любом порядке, но для более быстрого погружения предлагается изучать в таком порядке:

Что почитать

About

VContainer+UniTask+MessagePipe

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages