Blueprints
Blueprints против C++ в Unreal Engine — когда что использовать, компромиссы производительности.
12 вопросов
JuniorТеорияОчень частоВ чём разница между Actor Blueprint и Level Blueprint?
В чём разница между Actor Blueprint и Level Blueprint?
Actor Blueprint — переиспользуемый класс, который можно инстанцировать много раз на любом уровне. Level Blueprint — единственный граф, уникальный для одного уровня, для скриптинга уровня и ссылок на размещённых актёров. Его нельзя инстанцировать или переиспользовать.
Типичные ошибки
- ✗Менять роли местами — считать переиспользуемым классом Level Blueprint
- ✗Думать, что Level Blueprint можно инстанцировать, как Actor Blueprint
- ✗Считать, что Actor Blueprints — это превью только для редактора
Уточняющие вопросы
- →Почему Level Blueprint может ссылаться на конкретных размещённых актёров, а Actor Blueprint — нет?
- →Когда вообще уместно что-либо скриптить в Level Blueprint?
JuniorТеорияОчень частоКогда стоит использовать Blueprints, а когда C++ в Unreal Engine 5?
Когда стоит использовать Blueprints, а когда C++ в Unreal Engine 5?
Blueprints — для быстрой итерации, дизайнер-френдли логики и разового геймплея. C++ — для производительно-критичных систем, расширений движка и кода, который должен быть diff-able и тестируемым.
Типичные ошибки
- ✗Считать Blueprints медленными без измерений.
- ✗Класть сильно связанный геймплей в C++, где дизайнеры не могут итерировать.
Уточняющие вопросы
- →Как компилируются ноды Blueprints?
- →Когда оверхед Blueprint VM имеет значение на практике?
JuniorТеорияЧастоКак отлаживать логику Blueprint в Unreal Engine 5?
Как отлаживать логику Blueprint в Unreal Engine 5?
Ставьте брейкпоинты на ноды, чтобы приостановить выполнение и шагать по графу с отслеживаемыми переменными. Используйте Print String и visual logger для значений вживую, панель Blueprint Debugger для стека вызовов и подсказки при наведении на пины для просмотра данных в проводах.
Типичные ошибки
- ✗Не знать, что графы Blueprint поддерживают брейкпоинты на нодах и пошаговое выполнение
- ✗Полагаться только на Print String, когда Blueprint Debugger даёт больше
- ✗Думать, что для отладки нужно сначала перевести всё в C++
Уточняющие вопросы
- →Что окно watch даёт сверх наведения на пин для чтения значения?
- →Как отлаживать проблему Blueprint, которая воспроизводится только в упакованной сборке?
MiddleТеорияЧастоКак избежать спагетти-Blueprints в растущем проекте на Unreal Engine 5?
Как избежать спагетти-Blueprints в растущем проекте на Unreal Engine 5?
Разбивайте логику на маленькие именованные функции и свёрнутые графы, используйте event dispatchers вместо прямых cast, предпочитайте композицию через компоненты. Добавляйте reroute-ноды и блоки комментариев, а стабильные тяжёлые системы переносите в базовые классы на C++.
Типичные ошибки
- ✗Держать всё в одном огромном event graph вместо именованных функций
- ✗Злоупотреблять прямыми cast, создающими жёсткую связанность между Blueprints
- ✗Централизовать ссылки в Level Blueprint как глобальном хабе
Уточняющие вопросы
- →Почему event dispatchers снижают связанность по сравнению с прямым cast?
- →Как перенос логики в базовый класс на C++ помогает держать дочерние Blueprints чистыми?
MiddleТеорияЧастоКогда стоит переносить логику из Blueprint в C++ в Unreal Engine 5?
Когда стоит переносить логику из Blueprint в C++ в Unreal Engine 5?
Переносите логику в C++, когда она производительно-критична, выполняется каждый тик, должна переиспользоваться как базовый класс, требует юнит-тестов или стала слишком сложной для diff и ревью. Дизайнерскую, быстро итерируемую логику оставляйте в Blueprints.
Типичные ошибки
- ✗Считать, что Blueprints нельзя поставлять в упакованной сборке
- ✗Переписывать всё в C++ ради мелкого прироста, который дизайнеры потом не могут настраивать
- ✗Думать, что выбор о размере на диске, а не о производительности и сопровождаемости
Уточняющие вопросы
- →Как сохранить настраиваемость для дизайнера после переноса логики из Blueprint в C++?
- →Какие признаки в графе Blueprint говорят, что пора рефакторить в C++?
MiddleТеорияЧастоКак выстроить базовый класс на C++ с дочерним Blueprint в UE5?
Как выстроить базовый класс на C++ с дочерним Blueprint в UE5?
Размещайте основную логику и производительно-критичные системы в базовом классе на C++. Открывайте точки расширения через BlueprintImplementableEvent, а настраиваемые данные — через UPROPERTY(EditAnywhere), затем делайте дочерний Blueprint для визуала и настройки.
Типичные ошибки
- ✗Оставлять базу на C++ пустой и писать всю логику в дочернем Blueprint
- ✗Забывать, что переопределяемым точкам нужны
BlueprintImplementableEvent/BlueprintNativeEvent - ✗Думать, что наследование Blueprint копирует члены, а не переиспользует базу
Уточняющие вопросы
- →Когда для точки расширения выбрать
BlueprintNativeEventвместоBlueprintImplementableEvent? - →Как держать разделение C++/Blueprint стабильным, чтобы смена родителя позже оставалась дешёвой?
MiddleТеорияЧастоКак открыть C++-системы дизайнерам в Unreal Engine 5?
Как открыть C++-системы дизайнерам в Unreal Engine 5?
Помечайте функции UFUNCTION(BlueprintCallable), а свойства — UPROPERTY(EditAnywhere, BlueprintReadWrite). Добавляйте категории, подсказки и ограничения для удобного поиска и открывайте точки BlueprintImplementableEvent, чтобы дизайнеры расширяли C++ из Blueprint.
Типичные ошибки
- ✗Думать, что любой публичный C++-метод вызывается из Blueprint без
UFUNCTION - ✗Пропускать категории и подсказки, оставляя дизайнеров гадать о назначении нод
- ✗Считать, что Blueprint не может вызывать нативный код, а только читать открытые значения
Уточняющие вопросы
- →Когда выбрать
BlueprintImplementableEventвместоBlueprintNativeEvent? - →Как мета-спецификаторы вроде
ClampMinилиCategoryулучшают работу дизайнера?
MiddleТеорияЧастоКаковы риски размещения игровой логики в Level Blueprint?
Каковы риски размещения игровой логики в Level Blueprint?
Логика в Level Blueprint не переиспользуется между уровнями, плохо поддаётся diff и слиянию и раздувает один монолитный граф. Она создаёт скрытые зависимости от конкретных актёров уровня, поэтому при копировании или рефакторинге уровня логика молча ломается.
Типичные ошибки
- ✗Считать, что логика Level Blueprint переносима на другие уровни
- ✗Думать, что один Level Blueprint общий для всех карт
- ✗Считать, что Level Blueprints вырезаются из упакованных сборок
Уточняющие вопросы
- →Где должен жить скриптинг конкретного уровня вместо Level Blueprint?
- →Как Level Blueprint усложняет слияния в системе контроля версий в команде?
MiddleТеорияИногдаКакой геймплейной логикой должны владеть дизайнеры, а какой — программисты в UE5?
Какой геймплейной логикой должны владеть дизайнеры, а какой — программисты в UE5?
Дизайнеры владеют настройкой, связыванием контента и быстро итерируемым ощущением геймплея в Blueprints. Программисты владеют ядром систем, производительно-критичным кодом, сетью и общими фреймворками в C++. Слой C++ открывает параметры и точки расширения для дизайнеров.
Типичные ошибки
- ✗Отдавать дизайнерам сеть и ядро фреймворков, потому что Blueprint кажется проще
- ✗Полностью запрещать геймплей в Blueprint и считать его весь техдолгом
- ✗Считать, что Blueprint и C++ взаимозаменяемы для любой геймплейной задачи
Уточняющие вопросы
- →Как это разделение владения меняет проектирование C++-API для дизайнеров?
- →Что идёт не так, когда дизайнеры владеют реплицируемой геймплейной логикой в Blueprint?
SeniorПроизводительностьИногдаКак профилировать и снизить накладные расходы Blueprint VM при тиках сотен акторов?
Как профилировать и снизить накладные расходы Blueprint VM при тиках сотен акторов?
Профилируйте через stat game, Unreal Insights и стат Blueprint VM, чтобы найти стоимость на тик; каждый узел Blueprint несёт накладные расходы диспетчеризации VM. Переносите горячую тиковую логику в C++, отключайте ActorTick где можно, батчите обновления и заменяйте тиковые циклы таймерами или событиями.
Типичные ошибки
- ✗Считать, что узлы Blueprint бесплатны в рантайме, ведь граф «компилируется»
- ✗Оставлять
ActorTickвключённым на каждом акторе вместо таймеров или событий - ✗Профилировать только GPU-кадр и упускать стоимость диспетчеризации VM на CPU
Уточняющие вопросы
- →Как решить, какие горячие узлы портировать в C++, а не реструктурировать граф?
- →Когда замена тикового цикла таймером тонко меняет поведение геймплея?
SeniorДизайнИногдаВ команде, где C++-инженеры владеют базовыми классами, а дизайнеры строят на них геймплей в системе визуального скриптинга Blueprints, инженерам нужно продолжать рефакторить внутренности C++, при этом графы дизайнеров должны и дальше компилироваться. Дизайнеры ссылаются из графов на функции, свойства и иерархии классов C++ по имени, и эти ссылки молча ломаются при смене имени или сигнатуры либо при смене родителя класса. Опишите, как вы спроектируете границу C++/Blueprint так, чтобы внутренний рефакторинг был безопасным. Требования: открытая движку поверхность считается стабильным контрактом; внутреннюю реализацию можно свободно реорганизовывать, не трогая эту поверхность; у дизайнеров есть санкционированные точки расширения; а переименования и смена родителя обрабатываются так, чтобы существующие графы дизайнеров не ломались.
В команде, где C++-инженеры владеют базовыми классами, а дизайнеры строят на них геймплей в системе визуального скриптинга Blueprints, инженерам нужно продолжать рефакторить внутренности C++, при этом графы дизайнеров должны и дальше компилироваться. Дизайнеры ссылаются из графов на функции, свойства и иерархии классов C++ по имени, и эти ссылки молча ломаются при смене имени или сигнатуры либо при смене родителя класса. Опишите, как вы спроектируете границу C++/Blueprint так, чтобы внутренний рефакторинг был безопасным. Требования: открытая движку поверхность считается стабильным контрактом; внутреннюю реализацию можно свободно реорганизовывать, не трогая эту поверхность; у дизайнеров есть санкционированные точки расширения; а переименования и смена родителя обрабатываются так, чтобы существующие графы дизайнеров не ломались.
Считайте поверхность UFUNCTION/UPROPERTY контрактом: держите открытые сигнатуры, имена и иерархию классов стабильными, а внутреннее устройство рефакторите приватно. Используйте точки расширения BlueprintNativeEvent и интерфейсы, версионируйте данные и переименовывайте через Core Redirects, чтобы рефакторинг не ломал графы дизайнеров.
Типичные ошибки
- ✗Считать открытые сигнатуры
UFUNCTION/UPROPERTYсвободно рефакторимым кодом - ✗Переименовывать или удалять открытые члены без добавления Core Redirects
- ✗Менять родителя C++-класса, не проверив, на что опираются графы дизайнеров
Уточняющие вопросы
- →Как Core Redirects позволяют переименовать открытую функцию, не ломая BP?
- →Когда границей лучше сделать
UInterface, а не базовый класс?