Функции, макросы и переиспользование логики
Урок про то, как не дублировать логику в Blueprint: функции, макросы и их различия.
Функция Blueprint — это отдельный граф с входными параметрами и возвращаемыми значениями, который можно вызывать из других графов как одну ноду.
Зачем выносить логику в функции
Когда одна и та же цепочка нод нужна в нескольких местах, копировать её — плохая идея: при изменении придётся править все копии. Функция решает это: вы пишете логику один раз, а потом вызываете её одной нодой. Это тот же принцип, что и функции в обычном коде, только нарисованный.
Создание функции
Функция создаётся в панели My Blueprint кнопкой плюс рядом с Functions. У неё есть нода входа (с параметрами) и, при необходимости, нода Return (с результатом). Параметры и возвращаемые значения настраиваются в Details функции.
Функция: CalculateDamage(Base, Multiplier) -> Float [Вход: Base, Multiplier] --> [Multiply] --> [Return: результат] Вызов в графе: [CalculateDamage Base=10 Multiplier=2] --(Float=20)--> [Apply]
Функция против макроса
Кроме функций, есть макросы. Внешне похожи, но различия важны.
| Свойство | Функция | Макрос |
| Несколько выходов потока | Нет (один поток) | Да (можно ветвить) |
| Может содержать задержку (Delay) | Нет | Да |
| Своя нода на графе | Да, чистый вызов | Подставляется как «копипаста» |
| Переиспользование между блюпринтами | Легко (в т.ч. через интерфейсы) | Через Macro Library |
Правило простое: если логике нужны несколько выходов потока или задержка — берите макрос; в остальных случаях функция чище и быстрее.
Чистые функции (Pure)
Функцию без побочных эффектов, которая только считает и возвращает значение, можно пометить как Pure. У неё нет белых пинов потока — она вычисляется автоматически, когда нужен её результат. Геттеры и математические расчёты обычно делают Pure.
Как работает под капотом
Функция компилируется в отдельную подпрограмму в байт-коде. Вызов функции — это переход в неё и возврат обратно. Макрос же при компиляции разворачивается прямо в месте использования (инлайнится), как будто вы скопировали его ноды туда. Поэтому макрос может иметь задержку и несколько выходов, а функция — нет.
Частые ошибки
- Ставить Delay в функцию. Функции не поддерживают задержки — для этого нужен макрос или сам граф события.
- Делать Pure-функцию с побочными эффектами. Pure может вызываться неожиданно много раз; в ней нельзя менять состояние.
- Дублировать логику вместо функции. Это создаёт ад при поддержке.
Интерфейсы Blueprint
Когда логику нужно вызвать у объекта, точный класс которого вы не знаете, на помощь приходят Blueprint Interface. Интерфейс — это набор объявленных функций без тела, своего рода контракт: «любой, кто реализует этот интерфейс, умеет такие действия». Например, интерфейс Interactable с функцией Interact могут реализовать дверь, сундук и рычаг по-своему. Игрок, нажав «использовать», просто вызывает Interact у того, на что смотрит, не зная и не заботясь, что это конкретно за объект.
Это мощный приём для расширяемого кода. Добавляя новый интерактивный предмет, вы реализуете в нём интерфейс — и он автоматически работает с уже существующей системой взаимодействия, без правки кода игрока. Интерфейсы избавляют от длинных проверок «а это дверь? а это сундук?» и держат логику чистой.
Итоги
- Функция выносит повторяющуюся логику в один вызов с параметрами и результатом.
- Макрос отличается: поддерживает несколько выходов потока и задержки, но инлайнится.
- Pure-функции без пинов потока хороши для геттеров и расчётов.
- Функции компилируются в подпрограммы, макросы разворачиваются в месте вызова.