На этой странице представлен обзор PaddleBallSOдемонстрационного проекта-компаньона для электронной книги Создание модульной архитектуры игр в Unity с помощью ScriptableObjectsи объясняет, как он использует паттерны проектирования и модульность в своей архитектуре кода.
Это первое из серии шести мини-руководств, созданных для того, чтобы помочь разработчикам Unity в работе с демонстрацией, которая сопровождает электронную книгу. Демонстрация вдохновлена классической механикой аркадных игр с мячом и веслом и показывает, как ScriptableObjects может помочь вам создать компоненты, которые поддаются тестированию, масштабируются и удобны для дизайнеров.
Вместе электронная книга, демонстрационный проект и эти мини-руководства предоставляют лучшие практики использования паттернов программирования с классом ScriptableObject в вашем проекте Unity. Эти советы помогут вам упростить код, уменьшить потребление памяти и способствовать повторному использованию кода.
В эту серию вошли следующие статьи:
- Разделите игровые данные и логику с помощью ScriptableObjects
- Использование перечислений на основе ScriptableObject в проекте Unity
- Использование объектов ScriptableObjects в качестве объектов делегатов
- Использование ScriptableObjects в качестве каналов событий в игровом коде
- Как использовать набор времени выполнения на основе ScriptableObject
Прежде чем вы погрузитесь в демонстрационный проект ScriptableObject и эту серию мини-руководств, помните, что в своей основе паттерны проектирования - это всего лишь идеи. Они применимы не ко всем ситуациям. Эти приемы помогут вам освоить новые способы работы с Unity и ScriptableObjects.
У каждой модели есть свои плюсы и минусы. Выбирайте только те, которые приносят значительную пользу вашему конкретному проекту. Ваши дизайнеры в значительной степени полагаются на редактор Unity? Шаблон на основе ScriptableObject может стать хорошим выбором, чтобы помочь им сотрудничать с вашими разработчиками.
В конечном счете, лучшая архитектура кода - это та, которая подходит вашему проекту и команде.
В центре PaddleBallSO - классическая игра, положившая начало современным видеоиграм: два игрока, два весла и мяч.
Акцент здесь сделан на инфраструктуре, а не на игровой механике. Считайте это "игровой сантехникой" - менее гламурной, но жизненно важной основой, которая обеспечивает работу приложения.
Этот проект посвящен тому, как ScriptableObjects могут работать за кулисами, чтобы создать единое приложение. Используйте их для создания универсальных игровых систем, которые упрощают сопровождение проектов и способствуют многократному использованию кода. Вы также можете использовать их для получения данных об игроках, управления состоянием игры, внутриигровым поведением и т. д.
Проект PaddleBallSO совместим с последней версией Unity Long Term Support (LTS), на данный момент 2022 LTS. Он включает в себя UI Toolkit для создания пользовательского интерфейса во время выполнения программы и Input System для обработки пользовательских данных.
Найдите и загрузите проект в репозитории GitHub.
Загрузите Bootloader_scene или включите Load Bootstrap Scene on Play в меню GameSystems. Войдите в режим воспроизведения, чтобы начать.
Хотя они не являются специфическими для ScriptableObjects, в демонстрационном проекте используется пара общих приемов, помогающих запустить игровое приложение в последовательном и предсказуемом состоянии.
Scene Bootstrapper (или загрузчик) - это скрипт расширения редактора, отвечающий за установку начального состояния игры. Этот код инициализации отделен от игровой логики и обеспечивает правильную настройку всех зависимостей для объектов сцены.
Чтобы избежать проблем с зависимостями, бутстраппер настраивает основные игровые объекты, менеджеры или сервисы при загрузке сцены.
Если ваше приложение Unity состоит из нескольких сцен, загрузчик может принудительно загрузить определенную сцену загрузчика, которая является первой сценой из настроек сборки. При выходе из режима воспроизведения редактор перезагружает предыдущую сцену.
Другой компонент загрузочной сцены, менеджер последовательностей, может инстанцировать необходимые префабы при загрузке сцены. В этом конкретном демо-проекте все, что необходимо для создания игры, является префабом, включая камеру, SplashScreen, UI-меню и SceneLoader.
Затем SceneLoader аддитивно загружает (и выгружает) любые игровые сцены по мере необходимости. В большинстве случаев эти сцены состоят в основном из префабов.
Сцены проекта
Каждый уровень мини-игры представляет собой отдельную сцену Unity и отображается в Build Settings. Отключите SceneBootstrapper в меню GameSystems, если вы хотите изучить эти отдельные сцены.
Многие проекты также включают в себя область для главного меню после сцены bootstrap. В этом упрощенном демо-проекте отсутствует сцена главного меню.
Используйте меню Play и Pattern, чтобы протестировать PaddleBallSO, который включает в себя:
- Демонстрации паттернов проектирования, или "кусочные" примеры, которые показывают конкретные приемы и иллюстрируют каждый паттерн в отдельности
- Мини-игры, объединяющие их в функциональные, работающие образцы
Папка Core содержит неспецифические для приложения части кодовой базы, такие как базовые скрипты шаблонов, управление сценами и логика пользовательского интерфейса. Это более общие классы, которые могут применяться в различных приложениях.
Пример игры воссоздает культовый 2D-симулятор физики и демонстрирует возможности паттернов проектирования на основе ScriptableObject.
Однако прежде чем погружаться в паттерны, вам стоит ознакомиться с MonoBehaviours, из которых состоит приложение. Как и следовало ожидать, такие компоненты, как скрипты Paddle, Ball, Bouncer и ScoreGoal, управляют основным игровым процессом.
Несколько скриптов менеджера более высокого уровня управляют игровым процессом:
- GameManger управляет состояниями игры (начало, конец, сброс), инициализирует игровые компоненты, управляет пользовательским интерфейсом и реагирует на события.
- GameSetup работает с GameManager, чтобы установить мяч, весла, стены и ворота.
- ScoreManager обновляет значения очков, обрабатывает игровые события и управляет обновлениями пользовательского интерфейса для отображения очков.
Эти MonoBehaviours работают с вашими ScriptableObjects. Они играют важную роль в соединении этих компонентов, чтобы они могли общаться и обмениваться данными между собой.
События играют важную роль в коммуникации между различными частями проекта. Они связывают эти управляющие скрипты с другими объектами сцены и пользовательским интерфейсом. Эта событийно-ориентированная архитектура помогает сделать код более организованным и отлаживаемым.
Мы также привели упрощенные демонстрационные примеры для каждого из наиболее распространенных паттернов ScriptableObject. По мере ознакомления с ними вы начнете понимать, как ScriptableObjects лежат в основе архитектуры мини-игры.
Мы могли бы сделать мини-игру с гораздо меньшим количеством строк кода, но эта демонстрация посвящена паттернам проектирования с использованием ScriptableObjects. Обратите внимание, что многие из этих паттернов можно реализовать и без ScriptableObjects.
Решите всей командой, как каждый паттерн может быть применен к вашему проекту, и выберите тот подход, который подходит вам больше всего.
Модульность при разработке программного обеспечения подразумевает разбиение приложения на более мелкие и независимые части. Эти модули служат конкретным целям и могут разрабатываться и тестироваться отдельно.
Каждый небольшой набор объектов функционирует как единое целое и управляет одним аспектом игры. Это может быть что угодно: управление вводом данных игроком, управление физикой или подсчет очков.
Изучая сценарии проекта, обратите внимание на следующие основные моменты:
- Создавайте свои сцены из префабов: Вы заметите, что большинство сцен в проекте - это просто наборы префабов с минимальными переопределениями. Сборные конструкции по своей сути обеспечивают модульность. Устранение неполадок в работе функции сводится к тестированию конкретного префаба в отдельности. Как и ScriptableObjects, Prefabs - это активы уровня проекта, которые можно использовать повторно и совместно в нескольких сценах.
- Используйте ScriptableObjects для хранения данных (и не только): Избегайте использования MonoBehaviours для хранения статических данных геймплея. Вместо этого используйте ScriptableObjects для лучшего повторного использования. Вы также можете передать определенную игровую логику объектам ScriptableObjects или поручить им взаимодействие между объектами сцены.
- Отдельные заботы: Четко разграничьте данные, логику и пользовательский интерфейс в своем проекте. Это повышает удобство работы с кодом и упрощает отладку. В нашей системе экранов меню используется новый набор инструментов UI Toolkit. Эта система пользовательского интерфейса реализует рабочий процесс, который отделяет интерфейс от логики, лежащей в его основе. Для получения более подробной информации ознакомьтесь с Проектирование и реализация пользовательского интерфейса в Unity электронная книга.
- Минимизируйте зависимости: Уменьшение зависимостей между компонентами облегчает модификацию или замену частей проекта, не вызывая непредвиденных проблем.
- Используйте события для общения: События обеспечивают свободное взаимодействие между компонентами, позволяя им посылать друг другу сообщения без прямой зависимости. Вы можете еще больше разделить их с помощью "каналов событий" на основе ScriptableObject.
- Избегайте ненужных синглтонов: Шаблоны проектирования Singleton могут быть полезны, но только в тех случаях, когда необходим единственный экземпляр класса. Чрезмерное использование синглтонов может привести к созданию тесно связанного кода и затруднить тестирование. Пропустите синглтон, если он не нужен.
Рефакторинг большого монолитного скрипта на более мелкие части способствует многократному использованию и масштабируемости. Это приводит к улучшению совместной работы команды и упрощению тестирования.
Мы создали проект PaddleBallSO, чтобы продемонстрировать возможности использования ScriptableObject. Вот несколько конкретных мест, где вы увидите их в действии:
- Объект GameDataSO ScriptableObject служит центральным контейнером данных для игровых настроек. Отредактируйте общие данные один раз, а затем передайте их другим объектам, которым они нужны.
- Мини-игры опираются на многочисленные каналы событий, чтобы взаимодействовать между собой разрозненным образом. Эти события, основанные на ScriptableObject, составляют основу того, как объекты посылают друг другу сообщения.
- При воспроизведении звука используется объект-делегат на основе ScriptableObject, чтобы отделить логику от компонента MonoBehaviour.
- Мы используем перечисление на основе PlayerIDSO ScriptableObject, чтобы различать "команды" между игроком1 и игроком2.
- Объект LevelLayoutSO ScriptableObject служит контейнером данных для начальных позиций игровых элементов, таких как весла, ворота, стены и мяч. Это позволяет легко изменять макеты уровней как внутри Unity, так и извне через экспортируемые JSON-файлы. Моддинг уровней за пределами Unity может способствовать творчеству игроков и обмену пользовательскими макетами.
Не забудьте заглянуть в демо-версии шаблонов, чтобы узнать о некоторых дополнительных возможностях!
Хотя ScriptableObjects могут быть мощным инструментом для хранения игровых данных и оптимизации рабочего процесса, важно использовать их эффективно, чтобы не загромождать проект.
Вот несколько лучших практик использования ScriptableObjects в Unity:
- Сохраняйте модульность и упорядоченность данных: Используйте отдельные объекты ScriptableObject для разных типов данных (например, один для статистики игрока, другой для поведения врага и т.д.). Разбейте сложные данные на более мелкие части, которыми легко управлять.
- Используйте папки и соглашения об именовании: ScriptableObjects могут помочь сократить количество кода в ваших скриптах, но в качестве компромисса придется иметь дело с большим количеством активов в папках проекта. Правильное именование и организация каталогов помогут эффективно управлять этими ScriptableObjects. Ознакомьтесь с нашим руководством по стилю кода, чтобы получить советы по именованию.
- Избегайте чрезмерного использования ScriptableObjects: ScriptableObjects - это замечательные контейнеры данных, но важно не злоупотреблять ими. Помните, что ScriptableObjects могут усложнить ваш проект, поэтому используйте их только в тех случаях, когда они приносят очевидную пользу. (Например, не используйте их для сохранения постоянных данных).
- Регулярно создавайте резервные копии данных: Изменения в ScriptableObjects происходят "вживую" во время выполнения и сохраняются как файлы активов. Чтобы избежать потери данных, регулярно создавайте резервные копии проекта. Используйте программное обеспечение для контроля версий, чтобы отслеживать изменения в объектах ScriptableObjects.
- Используйте окно Инспектора: Одним из ключевых преимуществ ScriptableObjects является то, что они сериализуемы и отображаются в Инспекторе. Воспользуйтесь интерфейсом редактора для просмотра и манипулирования данными, хранящимися в ScriptableObjects.
- Используйте пользовательские скрипты редактора в своих интересах: Объекты ScriptableObjects не могут ссылаться на объекты времени выполнения из иерархии сцены. Используйте сценарии редактора, чтобы сделать Инспектор более удобным интерфейсом, если вам нужно визуализировать эти объекты.
Следуя этим рекомендациям, вы сможете избежать распространенных ошибок при разработке.
Подробнее о паттернах проектирования с помощью ScriptableObjects читайте в электронной книге Создание модульной архитектуры игр в Unity с помощью ScriptableObjects. Вы также можете узнать больше о распространенных паттернах разработки Unity в электронной книге Level up your code with game programming patterns.