Архитектура движка
Существуют разные подходы к настройке игровой архитектуры, от комплексных решений, в которых игровая логика объединена с движком, до кучи отдельных модулей, каждый из которых отвечает за одну часть функциональности. Unigine находится где-то посередине этой шкалы, он включает в себя все, что нужно для реализации игры или другого 3D-приложения, за исключением логики приложения, сетей и ИИ. Unigine включает в себя только типичную игровую логику, общую для приложений всех типов, и это сделано намеренно.
Это может показаться не преимуществом, потому что для создания игры нужно много программировать и самостоятельно реализовывать общие функции, широко используемые в играх требуемого жанра. Тем не менее, отсутствие логики игры, ориентированной на определенный жанр, не так уж плохо, поскольку делает Unigine универсальной библиотекой, которую легко использовать в различных проектах. Более того, разработчики не привязаны к какому-то конкретному жанру, они могут экспериментировать сразу с несколькими жанрами, что крайне сложно, если используется специализированный движок. Например, сложно совместить шутер и гоночную игру на движке, созданном исключительно для шутеров от первого лица. Кроме того, Unigine позволяет подключать внешние модули, которые могут содержать специфичные для жанра функциональные возможности, а также могут использоваться повторно. Все это делает Unigine довольно гибкой базой для широкого спектра 3D-приложений.
Понять архитектуру Unigine очень важно как для разработчиков, так и для создателей контента. Первые будут знать, что им разрешено делать, чего они могут достичь и чего ожидать от Unigine. Последние поймут, как будет обрабатываться их контент. Вот почему эта статья представляет собой краткий общий обзор рабочего процесса Unigine.
Схема ниже демонстрирует взаимосвязь между внутренними компонентами Unigine и различными внешними объектами.
Все начинается, когда настраиваемая логика приложения вызывает функции Unigine API. Эти вызовы могут выполняться напрямую с помощью UnigineScript или C / C ++. Первый вариант более предпочтителен, так как в этом случае программисту не нужно думать о многопоточности и управлении памятью. Кроме того, если приложение написано на UnigineScript, оно будет работать на каждой платформе, поддерживаемой Unigine. Компонент API загружает модули , которые расширяют функциональные возможности Unigine, если это требуется логикой приложения. Такие модули могут содержать, например, промежуточное ПО сторонних производителей.
Вызовы API передаются в интерпретатор , который инициализирует необходимые ресурсы: регистрирует расширения, загружает основные данные, файлы конфигурации, сценарии и файлы пользовательского интерфейса. Поскольку все эти ресурсы организованы в специальный каталог данных и, кроме того, могут быть упакованы , они загружаются с помощью компонента файловой системы . Кроме того, компонент файловой системы отслеживает порядок байтов файлов. Обратите внимание: если вы добавляете файлы в этот каталог после завершения инициализации, вам необходимо перезагрузить компонент файловой системы.
После инициализации в игру вступает менеджер мира . Он загружает файлы, необходимые для построения текущей сцены, и определяет набор видимых узлов, которые позже будут отправлены в компонент render . Менеджер мира также сообщает компоненту sound , когда и как воспроизводить звуки окружающей среды, какие источники расположены где-то в мире и имеют пространственные свойства. Конечно, менеджер мира взаимодействует с компонентом физики , который выполняет физические вычисления (обнаружение столкновений, решение суставов, плавучесть жидкости и т.д.) И, возможно, обновляет иерархию узлов. Короче говоря, менеджер мира не рисует объекты, не воспроизводит звуки и не выполняет физические вычисления самостоятельно. Вместо этого он делегирует эти задачи определенным компонентам.
Компоненты рендеринга и звука нуждаются в дополнительных ресурсах для выполнения своих задач: компоненту рендеринга нужны текстуры, сетки и анимации, а звуковому компоненту нужны звуки. Поэтому они просят менеджера ресурсов предоставить им то, что требуется. Задача менеджера ресурсов - загрузить необходимую графику и звуки, кэшировать их и выгружать, если они больше не требуются. Наличие менеджера ресурсов позволяет разработчику игры не думать о том, как и когда данные следует загружать и выгружать.
Если этого требует логика приложения, интерпретатор может также вызвать компонент GUI и заставить его рисовать пользовательский интерфейс через компонент рендеринга. В Unigine объекты GUI могут быть не только автономными, но и частью отображаемого виртуального мира. В последнем случае они управляются мировым менеджером, как и другие узлы.
Когда отображается визуализированное изображение, возможно, содержащее графический интерфейс, пользователь, естественно, начинает взаимодействовать с миром. Пользователь может влиять на мир с помощью различных устройств ввода. Входные данные с этих устройств отправляются в компонент графического интерфейса пользователя и компонент элементы управления . Компонент GUI обрабатывает ввод, обнаруживает элемент, на который щелкнули, и выполняет соответствующую функцию обратного вызова. Компонент управления обрабатывает ввод, не связанный с графическим интерфейсом, например, действия игрока в игре. Обратите внимание, что компонент GUI всегда получает входные данные перед компонентом управления и, следовательно, имеет более высокий приоритет.
Обработанный ввод передается интерпретатору, который определяет, влияют ли действия пользователя на параметры рендеринга или физики и т. д. Если да, интерпретатор просит соответствующие компоненты обновить изображение или вычисления. Если ввод пользователя что-то меняет в мире, менеджер мира обновляет набор видимых узлов и отправляет новые запросы указанным компонентам.
Эти действия повторяются в цикле, пока пользователь не выйдет из приложения.