Как посадить дерево

Как посадить дерево

EVALL

Я взялся за переработку старой игры «Ферма», сохранив графику, музыку и геймплей. Исходный код был написан без использования современных подходов, что привело к множеству проблем: обилие синглтонов, хаотичная логика в методах Awake/Start/OnEnable и сопутствующие ошибки и гонки инициализаций.


Скриншот из исходника

Главная цель в разработке — избавиться от этих проблем и получить новый опыт в разработке. Я хочу создать чистый, масштабируемый и легко поддерживаемый код, используя современные инструменты и архитектурные паттерны.


Предыстория:

На первый взгляд, задача казалась простой: переноси игру по частям в новый проект вот и все. Я решил начать с самого "главного" - создания карты. В старой игре статическая часть была выполнена из GameObject'от с компонентом SpriteRenderer и батчилась нормально, вот интерактивные элементы карты - деревья и камни, не батчились! Причина была в том, что они анимированы Animator'ом и состояли из 3х спрайтов, каждый !


Шаг первый - создание минимальной архитектуры

Импортировал в проект UniTask, так как мне не нравятся корутины. R3 - так как буду его изучать в этом проекте. Фраемворк Reflex - в качестве DI . Создал точку входа в приложение, загрузчик сцен, отдельный, переиспользуемый компонент экрана загрузки, которому можно передавать шаги (Func<UniTask> Taskstring Description), все настроил и забиндил в контейнер Reflex’a.


Шаг второй - создание статической части карты

В Unity я уже несколько лет, но так вышло, что с 2D-проектами вообще не работал. Поэтому, когда дело дошло до карты, я решил не искать лёгких путей и сразу познакомиться с инструментом Tilemap.

Я решил, что эта часть карты не будет загружаться через Addressables, так что просто оставил её на сцене как обычный префаб. В плане оптимизации, конечно, есть куда расти. Из-за "кривых" спрайтов получилось довольно много лишних треугольников, да и всю карту можно отрисовывать за один проход, а не за четыре, как у меня сейчас. Но для начала, и это уже отличный результат!

Вот так выглядит новая карта

Шаг третий - дополнительные сервисы

  • Инициализатор сервисов

Я создал OrderedInitializerBase, который асинхронно запускает сервисы по заданным приоритетам из InitializationOrderSettings. Сервисы с одинаковым приоритетом стартуют параллельно благодаря UniTask.WhenAll, а те, что не указаны в конфиге, получают дефолтный порядок (999). Это решение интегрируется с DI-контейнером Reflex и работает с любым сервисом, реализующим IOrderedInitializable.

  • Менеджер токенов

Реализовал CancellationTokenManager для управления асинхронными операциями. Он предоставляет токены для жизненных циклов приложения, сцен и игровых объектов, автоматически отменяя их при выходе или смене сцены. Это предотвращает утечки ресурсов и упрощает контроль задач.

  • Система состояний

Представлена как GameStateProcessor и GameStateService для управления состояниями игры (загрузка, геймплей, инициализация). Каждое состояние (IGameState) поддерживает асинхронные переходы с токенами отмены, принимает параметры на вход, а изменения отслеживаются через реактивное свойство CurrentStateRx на базе R3.

  • Логирование

Адаптировал логгер от Reflex, добавив уровни (Development, Info, Warning, Error) и цветное форматирование в консоли Unity. Это помогает быстро находить проблемы и отслеживать работу системы.

Результат работы логгера, просто и понятно и можно вырубать уровни сообщений, а можно убрать из билда
  • Загрузка сцен

Переработал SceneLoader, чтобы он сначала загружал промежуточную пустую сцену (BootScene), а затем целевую. Он также автоматически обновляет настройки build settings через SceneLoadingConfig

  • Структура проекта

Я разбил проект на сборки (CoreGameplayCommon), чтобы поддерживать модульность и общий код выделить в Common.


Время Сажать Деревья!

Но, как оказалось, и здесь не всё так просто:

– Где именно их "сажать"?

– Как правильно загрузить спрайты деревьев?

– Как обойтись без использования аниматоров, но сохранить движение?

– Какой способ сортировки слоёв выбрать?

И это лишь малая часть вопросов, на которые у меня пока нет ответов.



P.S.:  На все ушла почти неделя ! А дерево так и не выросло на моей карте 🥲Сажать деревья сложно 😁


Следующая статья о том Как посадить дерево





Report Page