UENUM iteration in Unreal Engine

WILD

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

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

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

Естественно, я не хотел вручную создавать и настраивать каждый виджет — особенно зная, что список категорий может измениться позже. Мне нужно было что-то простое и многоразовое: просто запустить цикл For each, генерировать все на лету и, в идеале, чтобы это работало для любого перечисления, а не только для этого.

И выход нашлся ! Когда вы определяете UENU, Unreal автоматически генерирует все метаданные и создает соответствующий объект UEnum, который является UObject. Все, что вам нужно сделать, это правильно использовать эти данные.


Создание итератора uenum​

Для удобства мы будем использовать UBlueprintAsyncActionBase, хотя это не единственный способ.

Давайте создадим класс-наследник UEnumIterateAction.

Что мы здесь делаем?

Я не буду углубляться в UBlueprintAsyncActionBase — эта статья не об этом. Я просто расскажу о соответствующих моментах.

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

Делегат OnEnumIteration будет срабатывать на каждой итерации. Рассматривайте его как «асинхронный» вывод выполнения. Просто убедитесь, что используете значение типа uint8, поскольку именно так мы будем представлять элементы перечисления и преобразовывать их обратно в Blueprint.

Далее мы переопределяем функцию Activate из базового класса. Именно там находится основная логика — тело нашего вызываемого узла.

Поскольку IterateByEnum работает как конструктор, нам необходимо сохранить входные аргументы для использования в Activate. Поэтому мы добавим два поля-члена: EnumToIterate и bSkipMax.

На этом настройка завершена — переходим к реализации.

Реализация итератора​

Что здесь происходит?

Реализация нашей функции IterateByEnum довольно проста. Как уже упоминалось, она, по сути, работает как конструктор, поэтому мы не будем подробно останавливаться на этом.

Внутри функции Activate мы получаем доступ к сохраненному перечислению и перебираем его с помощью стандартного цикла for — точно так же, как и с массивом.

В Unreal Engine значения перечислений хранятся как int64, поэтому именно этот тип мы получаем при доступе к ним по индексу. Но для наших целей нам нужен тип Byte, поскольку это единственный тип, который Blueprints может преобразовать обратно в значение перечисления.

Также важно пропускать скрытые записи перечисления — они, как правило, и не предназначены для отображения.

Мы также добавили флаг, позволяющий при необходимости пропускать автоматически сгенерированную запись MAX, которая часто тоже не содержит никакого осмысленного значения. Поскольку MAX также хранится как int64, мы сравниваем исходное значение EnumValue с результатом GetMaxEnumValue перед преобразованием его в байт.


Результат​

Вызов функции итератора

Вызов функции итератора
Вывод значений перечисления

Вывод значений перечисления
Начальные значения перечисления

Начальные значения перечисления
Как видите, всё отлично работает!
 
Top Bottom