Назад в библиотеку
Цитирование: Павлов М.Ю. Разработка в Unity, особенности движка. // Материалы XV Международной научно-технической конференции «Информатика, управляющие системы, математическое и компьютерное моделирование»// М. Ю. Павлов, А.В. Боднар – Донецк: ДОННТУ, 2024. – C. 371 – 378

Разработка в Unity, особенности движка.

Автор: Павлов М.Ю., Боднар А.В.
Источник:«Информатика, управляющие системы, математическое и компьютерное моделирование» (ИУСМКМ-2024) : сб. материалов XV Междунар. науч.-техн. конф. в рамках X Междунар. Науч. форума ДНР; Т.2 Ред. кол.: Аноприенко А. Я. (пред.); Васяева Т. А.; Карабчевский В. В. [и др.]; от. ред. Р. В. Мальчева. – Донецк : ДонНТУ, 2024. - 451 с. ИУСМКМ-2024

Аннотация

Павлов М.Ю., Боднар А.В. Разработка в Unity, особенности движка. . В работе рассматривается игровой движок Unity, его направленность, возможности, особенности в создании объектов и другие элементы, выделяющие его среди остальных. Целью работы является разбор основных элементов Unity c целью описания специфики разработки приложений, описание сложностей эксплуатации движка, описание стандартов и их назначения.

Введение

Разработка – сложный и глубокий процесс, направленный на моделирование системы с конкретными задачами. В стремлении обеспечить качественную разработку рассматриваются различные подходы к программированию, языки программирования, архитектура и т.п. Рассматривая разработку игр, можно выделить множество особенностей, используемых различными движками программирования. Так, Unreal Engine внедрил средства визуальной разработки, используя технологию Blueprint. Технология строится на упрощении процесса разработки событий на основе node, в котором хранятся данные событий или функции. Эта технология стала развиваться, и теперь используется как ядро приложений, благодаря которому можно создавать практически любое событие на уровне или элемент интерфейса. Сейчас возможно создать целую игру на основе Blueprint, хоть на неё и будут наложены ограничения.

Особенности движка могут играть и ключевую роль: так, в движке Godot основной разработки является система node (далее – просто «узел») – грубо говоря, корневая система игры, которая и собирает все элементы воедино. Если в Unity для создания объекта используются компоненты, то в случае с Godot объектом является узел, чьи свойства описываются дочерними узлами. Таким образом, чтобы узнать свойства какого-либо узла, необходимо изучить узлы, которые находятся внутри него. Важным элементом в Godot являются скрипты, ведь к одному узлу может прилагаться только один скрипт, тем самым движок подводит разработчика к созданию иерархии с осмысленными названиями для разработки «объекта»; каждое свойство может дополнительно описываться вложенным в него скриптом.

Сегодня одним из самых популярных движков разработки игр считается Unity. Он прошел тернистый путь от движка для создания простой анимации до кроссплатформенного движка для создания игр. Основой Unity стал компонентно-ориентированных подход, основанный на представлении объекта в виде ряда компонентов, описывающих свойства и взаимодействие объекта с остальным миром. Такой подход сделали главной особенностью Unity, поэтому данная парадигма начала регулярно совершенствоваться и преображаться под современные тенденции в разработке игр – как стилистически, так и логически, образуя новые направления в программировании.

Таким образом, можно сделать вывод, что особенности движка могут задавать тенденции в разработке приложения, меняя привычный вектор разработки на тот, который предназначен для конкретной задачи, что позволяет реализоваться в выбранной области и развивать конкретную тему. В перспективе, если метод может быть оптимизирован и обладает достаточным функционалом для решения задачи, он обретает популярность в своих кругах и открывает новые приемы разработки, развивая сначала одну область, а потом дополняя другие. Например, система Blueprint теперь используется во многих движках, так как позволяет решать простые, не требующие оптимизации задачи. Система узлов с каждым годом сильнее совершенствуется. Узлы во многом направленны как на упрощение описания «объекта», так и на упрощение его настройки и последующей эксплуатации, и тем самым им удается решать проблемы компонентно-ориентированного подхода, для которого характерна сложность настройки объекта, производимая вручную. Но куда важнее правильная эксплуатация – она позволяет превратить движок в мощный инструмент, который оптимизирует решение поставленных задач благодаря сильным сторонам движка.

Основной интерфейс Unity

В первую очередь при работе с движком мы сталкиваемся с его интерфейсом. Интерфейс обладает ключевой значимостью для разработчика и в поддержке программы. Чем проще и направленней расположены объекты, тем проще с ним работать, и это правило распространяется не только на пользовательские приложения, но и приложений для разработки. В последнее время из-за высокой конкуренции каждый движок старается выделиться всем, чем может, и Unity не стал исключением.

Unity был создан в 2005 году. На ранних порах разработки интерфейса в основу лёг простой принцип, очень схожий с принципом программы для монтажа Final Cut под названием «drag-and-drop» [1] – перетаскиванием элементов программы между собой. Эту особенность реализовали лишь частично. И действительно – при сравнении версий Unity, старый движок, позволявший менять местами только незначительные объекты, кажется топорным и медленным. Хоть он в первую очередь создавался как приложение под Mac OS, впоследствии Unity переориентировался на Windows из-за расширения рынка пользователей операционной системы. В то время движок сталкивался со множеством оптимизационных проблем и совершенно не подходил для разработки приложений.

В настоящем времени движок считается эталоном качества интерфейса (рис 1). Дозволяется свободное перемещение всех элементов, увеличение, уменьшение и контроль видимости элементов интерфейса. Помимо этого, в Unity предлагает удобную работу с объектами, про которые мы поговорим позже.

основной интерфейс Unity

Рисунок 1 – основной интерфейс Unity

Инструментарий для работы с объектами сцены расположен в левом верхнем углу: в нем демонстрируются взаимосвязи элементов и их иерархические отношения «родитель-потомок». В нашем случае родительский объект «TableWithLamp» содержит в себе два дочерних – «Lamp» и «Table» (рис 2). Теперь «TableWithLamp» является главным, а его координаты становятся локальным центром для дочерних элементов. Таким образом можно создавать сложные объекты из нескольких объектов

иерархия сцены в Unity

Рисунок 2 – иерархия сцены в Unity

Справа находится «Inspector» (рис 3). Он содержит данные об объекте и компоненты, которыми наделен объект. Здесь разработчик может проследить, какие компоненты уже являются частью объекта, и добавить свои собственные компоненты или скрипты.

интерфейс «Inspector» объекта «Character Camera»

Рисунок 3 – интерфейс «Inspector» объекта «Character Camera»

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

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

Стандарты программирования и особенности кода в Unity

Любой язык программирования имеет свои стандарты. Они необходимы для порядка: программист может взглянуть на код и сразу понимать, что происходит в данном участке. Unity, по большей части, использует стандарты C#, такие как PascalCase, где каждое слово публичного поля именуется с большой буквы, а также _camelCase, где закрытые поля начинаются с ‘_’ и первое слово – с маленькой буквы, а остальные – с большой. Сами по себе эти правила и без того широко применялись, но в Unity они приобрели значимость, связанную с настройкой объекта.

Остальной код в скриптах использует базовые понятия С#, такие как «у каждой скобки должна быть своя линия» и стандартные отступы. То же касается интерполяции строк вместо использования LogFormat [3].

Говоря о стандартах и стилистике кода в Unity, в первую очередь в голову приходит работа с компонентами и со внешними ссылками, используемыми в настройке компонентов. Для такой работы применяются атрибуты, которыми мы помечаем поля. Важное замечание: атрибуты можно применять к полям, методам и классам. Большая часть атрибутов должна находиться в квадратных скобках, чтобы Unity сразу смог их определить и найти. Главной особенностью Unity является работа с сериализацией полей, что напрямую показывает безопасность в использовании кода и обработке данных. Часто именно для этого используют атрибуты.

Атрибут SerializeField используется для объявления переменной в инспекторе, то есть для внешней обработки такой данной. Но этот атрибут можно использовать в паре: для этого применяется запись вида «[AtributeName1,…AtributeNameN]», притом каждый атрибут должен записываться стилистически правильно – так, словно это был вызов сторонней функции. И все же область применения этого атрибута несколько глубже. Публичные поля можно сериализовать – это позволяет конвертировать их в необходимый формат, например, JSON. Публичные поля по умолчанию доступны для сериализации, но вот закрытые поля можно будет сериализовать, только используя этот атрибут. Это важная особенность, так как классы типа MonoBehavior относятся к сериализуемым. Но для остальных необходим данный атрибут, который обозначает, что данные будут изменяться и подвергаться какому-то влиянию, хоть они при этом и не являются MonoBehavior.

Атрибут Range(Max, Min) описывается после другого атрибута и устанавливает ограничения для данной, которую можно ввести в инспекторе. Он обладает аналогами, которые работают по аналогичному принципу: Max(MaxValue) и Min(MinValue). Если же мы говорим о переменной формата string, то к ней можно применить атрибут Multiline(), который создает указанное поле с определенным количеством строк, и TextArea(), который позволяет использовать текст в многострочном стиле с автоматическом оберткой и полосами прокрутки, если текст превышает выделенную область.

Многие поля требуют подсказок, поскольку могут быть интуитивно сложными или иметь запутанную логику. В таком случае применяется атрибут ToolTip(Hint), где поле Hint и является подсказкой. В основном В основном этот атрибут используется для передачи вспомогательных смыслов и помощи геймдизайнеру в создании уровня.

Атрибут Header(HeaderString) позволяет добавить заголовок между полями, но редко используется, поскольку разделение ответственности между классами должно избавлять от необходимости выделять поля в отдельные группы. В то же время он хорошо подходит под классы-инициализаторы, чтобы выделить ответственность каждого инициализированного класса.

В случае, если мы хотим показать, что какое-то поле точно не должно находиться в инспекторе или сериализовываться извне, мы используем атрибут NonSerialized и HidenInspector. Названия полей говорят сами за себя.

ContextMenu является сложным атрибутом и применяется к методам, чтобы использовать их в инспекторе до запуска программы. Подобные атрибуты помогают с тяжелыми операциями, которые сложно было бы запускать на лету или при высокой нагрузке на систему. Тем самым атрибут способствует оптимизации. Либо же таким атрибутом можно протестировать работу какого-то метода, но куда интереснее использовать метод для шаблонного создания и последующего редактирования объектов в соответствии с текущими реалиями. Например, создание повторяющихся элементов, с которыми напрямую будет взаимодействовать данный компонент. Он имеет преимущество над префабами, поскольку не требует отдельно настраивать созданный объект к какому-то объекту, являющемуся системным скриптом.

Поскольку уже были затронуты связи между компонентами, нельзя забывать и про инструмент, позволяющий напрямую сказать, что скрипт не будет работать без определенного компонента или наоборот, а также не позволяяющий удалить этот компонент с объекта. Для этого необходим атрибут RequireComponent(typeof(ComponentName)).

Если же компонент – это часть какого-то объекта, то есть его дочерний элемент, и важно, чтобы он перемещался только со своим родителем, используется атрибут SelectBase. При выборе дочернего объекта в фокус попадает весь объект, а не только его элемент.

Также важную роль играет расположение строк, описывающих компонент. Это необходимо для понимания и обработки так же, как и работа с классами. То есть если кто-то опишет переменные после методов, это не будет считаться стилистической ошибкой, и компилятор пример такую запись, но программист, который будет использовать данный класс, может столкнуться с непониманием, а то и вовсе не заметить особенности класса, что, вероятно, приведет к проблемам в разработке. Общее построение полей должно иметь такой вид: блок полей с атрибутами, блок публичных свойств, блок приватных полей, свойства и методы. Каждый блок отделяется пустой строкой.

В первую очередь, используя базовые правила, мы упрощаем работу над проектом и тем самым позволяем другим программистам без вреда для производства вести разработку, а также упорядочиваем процесс, демонстрируя отношение к проекту и к коду, с которым работает программист [5]. Что касается особенностей программирования на Unity, важным плюсом является нейминг атрибутов, позволяющий без каких-либо проблем их запоминать и использовать: для этого всего лишь необходимо понимать, зачем они были придуманы и как объекты взаимодействуют в редакторе.

Выводы

В заключение стоит сказать, что разработка приложений на Unity является трудоемким процессом, в ходе которого возникает множество проблем не только на этапе разработки, но и в дальнейшем – при создании игры на сцене. Проблемы накапливаются на каждом из этапов, что в будущем приводит к огромным потерям во время выхода проекта или при тестировании. На избавление от этих проблем часто уходят огромные суммы и запасы времени. Многие проблемы тяжело решить, если программист плохо разбирается в интерфейсе программы и не использует базовые особенности Unity, направленные на облегчение разработки и дальнейшее развитие программы. Понимание того, зачем нужны эти элементы, не менее важно, ведь развитие движка происходит постепенно и под влиянием различных обстоятельств, и ориентация на компонентно-ориентированный подход является отличительной чертой движка. Было бы глупо отказываться от его главной особенности. Спроектировать и правильно настроить такую систему крайне сложно, а дальнейшее развитие проекта сталкивается с рядом проблем и зависимостей: в первую очередь проект будет зависеть от тимлида, на которого ложится ответственность не только по распределению работы, но и постоянный контроль над работами различного уровня. Заменять такого сотрудника и при стандартном ООП крайне сложно, но при использовании КОП это превращается практически в невыполнимую задачу. Конечно, у этого есть и плюсы – вводить новых сотрудников в проект достаточно просто. Чтобы избежать проблем с развитием и поддержкой программы, были придуманы различные стандарты и спецификации, помогающие в разработке и оптимизации проекта.

Это дает понять, что Unity – это движок, направленный на специфичную разработку с использованием КОП. Зная все особенности и принципы, которые используется для создания продукта на данном движке, можно строить сложные структуры и проекты, выполняющие поставленную перед ними задачу (конечно, не беря в расчет планирование и управление разработкой). Если же использовать особенности движка некорректно или не по назначению, это может усложнить разработку, а то и вовсе сделать её невыполнимой

Список использованной литературы

1. Хокинг Д. Unity - в действии. Мультиплатформенная разработка на C# // - 2-е издание - СПб : Питер, 2016. - 336 с.
2. Unity User Manual 2022.3 (LTS) // [Электронный ресурс]. - Режим доступа: https://docs.unity3d.com/Manual/UnityManual.html
3. unity-coding-standards // [Электронный ресурс]. - Режим доступа: https://leotgo.github.io/unity-coding-standards/
4. Роберт М. Чистый код: создание, анализ и рефакторинг Библиотека программиста. // перевод с английского - СПб.: Питер, 2013. - 464 с
5. Вирт Н. Программирование на языке Modula-2 // Вирт Н. – перевод с английского – Москва: Мир 1987 – 224 с.
6. Введение в компонентно-ориентированный подход к программированию habr // [Электронный ресурс]. - Режим доступа: https://habr.com/ru/articles/243479/
7. Троелсен, Э. Язык программирования C# 7 и платформы .NET и .NET Core, 8-е изд. : Пер. с англ. / Э. Троелсен, Ф. Джепикс. СПб. : ООО «Диалектика». – 2018. – с. 1328
8. Heinman G.T. Component-based software engineering : putting the pieces together // Heinman G.T. Concill W. T. - Boston : Addison-Wesley 2001 – 818 c.