Asynchrony in blueprints into Unreal Engine

WILD

Administrator
Staff member
ADMIN
SELLER
SUPREME
MEMBER
Joined
Jan 21, 2025
Messages
219
Reaction score
637
Deposit
0$

Предисловие​

Если вы какое-то время работали с Unreal Engine, вы, вероятно, сталкивались с узлами, которые позволяют вызвать функцию сейчас и получить результат позже , при этом продолжая выполнение после завершения функции.

Встроенные асинхронные узлы

Встроенные асинхронные узлы
Но когда вы попытаетесь создать свои собственные функции, вы быстро обнаружите, что не можете просто «углубиться» в их логику, как это делается с обычными функциями Blueprint.
Так как же создать свои собственные?

Вот тут-то и пригодится UBlueprintAsyncActionBase. Это ключ к созданию функций, которые ведут себя как автономные асинхронные узлы в Blueprints.


Создание собственных асинхронных узлов​

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

Для этого нам нужно создать новый класс C++, наследующий от UBlueprintAsyncActionBase.
В этом примере мы назовем его UAsyncAction.

Вызываемые функции​

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

Вот в чём хитрость — эти функции выступают в роли наших конструкторов .

Как видите, мы пометили их как BlueprintInternalUseOnly. Это важно, потому что фактические узлы, которые будут вызываться в Blueprint, будут генерироваться движком. Все, что нам нужно сделать, это определить правильные сигнатуры, а Unreal позаботится обо всем остальном.

Верните результат​

Хорошо, но как нам на самом деле получить желаемый результат?

Для этого мы определяем делегат: FOnAsyncDone OnAsyncDone. Каждый созданный нами асинхронный узел будет использовать этот делегат в качестве своего выходного параметра.

Благодаря этому делегату в Blueprints будет вывод выполнения OnAsyncDone, который вернет логическое значение с именем WasSuccessful.

Основная функция​

Мы определили вызываемые функции и присвоили им правильный результат.
Но поскольку это, по сути, конструкторы, куда же тогда помещается основная логика?

Вот тут-то и пригодится UBlueprintAsyncActionBase. У него всего одна действительно важная для нас функция: Activate(). Представьте её как BeginPlay() для вашего асинхронного узла.

Здесь будет храниться логика всех ваших пользовательских асинхронных функций. Да — всех до единой.

Кэш​

Поскольку реализация будет находиться внутри функции Activate(), и мы вызываем нашу логику через статические функции, нам нужен способ хранения аргументов.

Поэтому мы добавим соответствующие поля для их хранения.

Выполнение​

файл .cpp

Как видите, в наших статических функциях мы просто создаём экземпляр нашего класса и передаём в него аргументы. Поскольку у нас две разные функции, но одна общая реализация, мы используем флаг — bFirstFunction — для их различения.

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


Результат​

Итак, что же на самом деле делают наши две функции?

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

Вызов первого узла

Вызов первого узла
Результат первого узла

Результат первого узла
Как видите, первая функция работает — и работает асинхронно.

Асинхронность​

Вызов второго узла

Вызов второго узла
Результат второго узла

Результат второго узла
Как видите, асинхронный вывод второго узла сработал до того, как функция начала печать.
Именно поэтому я взял слово «асинхронный» в кавычки — потому что узел на самом деле не работает асинхронно.
Если ваша функция не выполняет никаких асинхронных действий внутри, она будет вести себя как обычная функция Blueprint — то есть она выполнит свой вывод, прежде чем перейти к следующему узлу.

Вот и всё — теперь вы знаете, как создавать асинхронные узлы Blueprint в Unreal Engine!
 
Top Bottom