🎮 Как использовать Blueprint для быстрого прототипирования игр на Unreal Engine 4?
Изучение Blueprint – лучший вариант быстрого старта в Unreal Engine. Статья проведёт читателей по основам Blueprint, расскажет о его применении и даст несколько советов по поводу баланса между C++ и BP.
Что нужно знать перед прочтением этой статьи?
Предполагается, что читатель уже базово знаком с Unreal Engine 4: умеет создавать проекты, приблизительно знает, где в интерфейсе что находится, а также имеет представление об основных концепциях движка. Также предполагается, что читатель знаком с программированием на любом императивном языке и имеет опыт работы с отладчиком (вне зависимости от языка программирования и IDE).
Что такое Blueprint?
Под Blueprint (BP) могут подразумевать две связанные, но всё-таки разные вещи: систему визуального программирования и созданные с помощью этой системы объекты. Суть этой системы заключается в программировании игровой логики посредством основанного на графах скриптового языка.
Как и многие подобные языки, он позволяет создавать классы и их экземпляры (объекты), которые зачастую называют просто блюпринтами.
Для чего нужен Blueprint?
Как ни странно, Blueprint нужен не только для программирования акторов (игровых объектов) и подобных игровых вещей. Приведём несколько примеров использования этого инструмента:
- UI: логика для виджетов может быть реализована в Blueprint;
- Анимации: в Unreal Engine есть понятие Animation Blueprint – фактически это особая версия BP, в которой имеются дополнительные фичи и целью которой является описание анимационной части поведения объекта;
- Расширения редактора: с помощью BP можно создавать так называемые Editor Utility, фактически представляющие собой скрипты для редактора. Их можно использовать для автоматизации рутинных задач или даже для серьезного дополнения возможностей редактора.
Какова польза от Blueprint?
Если же говорить о BP имея в виду классы и экземпляры классов, то их главным преимуществом является, пожалуй, возможность визуального создания игровых объектов: расположение различных компонентов (компонент – обособленная функциональность, предназначенная для переиспользования) в пространстве, а также их настройка прямо из редактора. Это аналогичная упомянутой в предыдущем абзаце идея, только касающаяся не логики, а данных – настроек компонентов.
Обзор редактора Blueprint и создание класса
Для создания BP-классов существует несколько путей, но основной – сделать т.н. ассет Blueprint из панели Content Browser. Необходимо щёлкнуть правой кнопкой мыши в Content Browser и выбрать Blueprint Class:
На следующем шаге необходимо выбрать базовый класс для создаваемого:
По двойному щелчку на созданном классе будет открыт редактор BP. Остановимся на нём (на скриншоте ниже создан BP-класс, наследник класса Actor):
- В левой верхней части расположена панель, где отображается иерархия компонентов BP-класса. Сразу под ней – панель, отражающая структуру класса: функции, BP-графы, макросы, переменные и делегаты.
- В средней части окна редактора расположена основная рабочая область, поделенная на вкладки. Вкладок может быть гораздо больше чем показано на скриншоте: к примеру, для каждой новой функции класса будет создана отдельная.
- Вкладка “Viewport”, отображает все компоненты класса в пространстве так, как они будут расположены при создании экземпляра этого BP-класса в игре. Здесь разработчик может перемещать, вращать и масштабировать компоненты, немедленно наблюдая результат манипуляций.
- Вкладка “Construction Script” позволяет задать функцию, вызываемую при создании экземпляра этого класса. Знакомые с объектно-ориентированным программированием читатели уже поняли, что речь идёт о BP-версии обычного конструктора. Вкладка “Event Graph” содержит логику обработки воспринимаемых классом событий.
- Панель “Details” в левой части редактора, отображает настройки самого класса, одного из его компонентов, переменной класса и т.д.
- Основная часть описанных ниже манипуляций будет сосредоточена во вкладке Event Graph и панели “My Blueprint”.
Переменные в Blueprint
Создадим унаследованный от Actor BP-класс, назовём его Bulb и с помощью кнопки “Add Component” добавим в него точечный источник света (Point Light Component
):
Создадим простую сцену, на которой расположим выполняющий роль пола куб, а посередине – наш актор:
Запустим проект и убедимся, что куб освещён скучным белым светом:
Вернёмся к нашему BP и с помощью кнопки “+ Variable” создадим новую переменную, используя которую будет можно задать цвет источника света. Назовём её LightColor
, выделим в секции “Variables” панели “My Blueprint” и переключимся на панель “Details”, где будут отображены настройки переменной:
Выберем тип “Linear Color” и установим флаг “Instance Editable”. Этот флаг позволит задавать значение переменной для каждого экземпляра класса.
Данные есть, теперь к логике. Перейдём в “Event Graph” к событию BeginPlay
. Это событие запустится, когда актор будет добавлен (заспаунен) на уровень. Потянем левой кнопкой мыши за отмеченный сиреневым элемент:
Отпустим левую кнопку мыши – тут же появится окно выбора функции. Снимем флаг “Context Sensitive” (без него редактор предложит все возможные функции, а не только те, которые укладываются в текущий контекст) и найдём функцию Set Light Color
компонента Point Light Component
:
Должно получиться так:
Белая линия означает порядок выполнения. Иначе говоря, белая линия – это возможный путь передачи управления из одной BP-ноды (узла BP-графа) в другую.
Цветные пины (pin) означают входные данные/выходные данные. Как видно на скриншоте, Set Light Color
ожидает три значения на входе:
- Target – объект, на котором будет вызвана функция. Здесь ожидается
Point Light Component
. Перетянем его зажатой левой кнопкой мыши из секции “Variables” панели “My Blueprint”. После отпускания кнопки мыши, появится выбор:
Нас интересует получение компонента, а не его перезапись, поэтому выбираем Get PointLight
. Соединим выходной пин создавшейся ноды с входным пином Target
ноды-вызова Set Light Color
:
New Light Color
– новый цвет для источника света. Его необходимо взять из созданной нами переменнойLightColor
. Для закрепления проделайте это сами.sRGB
– булев флаг. Значение задано на самой ноде: флаг отмечен – значение истино, снят – ложно.
После изменения BP его необходимо скомпилировать. Для этого есть специальная кнопка на панели инструментов в верхней части редактора.
При успешной компиляции кнопка будет гореть зелёным:
Перейдем к редактору уровня, выделим наш актор и обратимся к панели “Details”:
В разделе “Default” можно видеть созданную нами переменную Light Color
. Нажмем на квадратно-чёрную её часть и выберем какой-нибудь цвет. Запустим проект и убедимся, что источник света изменил цвет:
Операторы ветвления
Вернёмся к переменной LightColor
и сделаем из неё массив. Для этого необходимо нажать на иконку справа от типа переменной и выбрать иконку с квадратами три на три:
Вероятно, редактор попросит вас подтвердить: действительно ли вы хотите изменить тип переменной: смело отвечайте “Да”. После этого ваш граф сломается:
Чтобы это исправить, удалите ноду с LightColor
и перекомпилируйте BP.
Теперь когда мы можем задавать несколько цветов: давайте сделаем так, чтобы источник света менял цвет каждую секунду на следующий из массива PointLight
, а по завершении выключался.
Создадим новую переменную CurrentColorIndex
типа Integer
, скомпилируем BP и зададим переменной значение по умолчанию – 0
:
Создадим такую конструкцию:
Булево значение является результатом строгого сравнения значения CurrentColorIndex
и размера массива LightColor
. Внимательный читатель догадывается к чему идёт дело: к наивной реализации цикла.
В случае, если элементы в массиве ещё не закончились, взять текущий и установить цвет источника света равный этому элементу, подождать одну секунду, увеличить CurrentColorIndex
на один и перейти обратно к условию. Если элементы закончились, установить цвет в чёрный и завершить выполнение.
Добавим цветов в находящийся на уровне актор:
Запустив игру, проверим результат.
Циклы
Конструкцию выше можно с легкостью заменить на встроенный в BP цикл For Each
:
Запустим и убедимся, что всё работает. Ничего не работает? У меня тоже.
Это старый баг движка (или фича – уже никто не знает). Delay
внутри For each
игнорируется, поэтому цикл выполняется настолько быстро, что становится невозможным заметить реальную смену цвета, а лишь только черный экран.
Функции
Для возможности визуального отслеживания результатов работы нашего BP, вернём вариант с Branch
. В секции “Functions” панели “My Blueprint” создадим новую функцию SetColor
:
В панели “Details” добавим параметр для функции с именем NewColor
и типом Linear Color
:
Заметьте, для новой функции в рабочей области BP-редактора появилась новая вкладка. Перенесём туда вызов функции SetLightColor
на компоненте Point Light:
Заменим оба вызова Set Light Color
в Event Graph на вызов нашей функции:
Запустим проект и убедимся, что всё работает, как и работало.
Отладка Blueprint
В редакторе имеется встроенный отладчик, позволяющий устанавливать точки останова и просматривать значение переменных в BP прямо во время выполнения. Поставим точку останова на вызове Set Light Color
в функции Set Color
. Для этого кликните по ноде правой кнопкой мыши и выберите “Add Breakpoint”:
При запуске игры выполнение остановится на этой ноде, и вы сможете просмотреть значения переменных или, например, пошагово пройтись по следующим нодам.
Для управления выполнением в режиме отладки в верхней части редактора имеется множество кнопок, значение большинства из которых должно знакомо любому знакомому с отладчиками программисту:
Баланс между C++ и Blueprint
Для начала сравним C++ и Blueprint.
C++
- Код на C++ работает быстрее;
- C++ гораздо лучше справится с задачами, связанными с булевой логикой, математикой и большими системами;
- На C++ рекомендуется рекомендуется писать ядро игры и реализовывать критически важную функциональность;
- Часть функциональности и определённых в C++ данных можно держать закрытыми для Blueprint, не загрязняя ими API.
Blueprint
- Достаточно производительный, но медленнее C++;
- Blueprint гораздо проще использовать для прототипирования;
- Гораздо более быстрые итерации разработки, чем при использовании C++;
- Больше участников команды могут работать с Blueprint;
- Фактически каждый BP является ассетом. Иначе говоря BP – это контент. В некоторых случаях это важно.
Для команды из одного человека и небольшого проекта вполне приемлемо использовать только BP. Использование же только C++ (в любом проекте) вряд ли является обоснованным решением.
Вывод
Blueprint – система визуального программирования в UE, призванная увеличить количество участников команды, способных самостоятельно создавать игровую логику. Блюпринтами также называют определённые через эту систему классы. BP поддерживает все фичи обычных языков программирования: переменные, функции, операторы ветвления, циклы. В редакторе UE имеется встроенный отладчик BP. Перед началом проекта стоит серьезно задуматься о балансе между C++ и BP, которого стоит придерживаться.
Несмотря на кажущуюся простоту BP – система с большим количеством тонкостей, в особенности если смешивать её с C++. Полное изучение всех особенностей работы с BP может занять время. Удачи в обучении!