Макросы рефлексии: UCLASS, UPROPERTY, UFUNCTION
Урок объясняет загадочные макросы Unreal-C++ и зачем они нужны движку.
Рефлексия — это способность движка во время работы знать структуру классов: их поля, типы и функции. В Unreal её включают специальные макросы.
Почему обычного C++ недостаточно
В стандартном C++ после компиляции имена полей и функций исчезают — остаются лишь адреса в памяти. Но движку нужно знать структуру классов на лету: чтобы показать поля в Details, сохранить объект в файл, связать C++ с Blueprint, собрать мусор. Для этого Unreal добавляет свою систему рефлексии, а включается она макросами. Это плата за мощь: код выглядит непривычно, но эти макросы — основа всей интеграции.
Главные макросы
| Макрос | Что помечает | Зачем |
| UCLASS() | Класс | Регистрирует класс в системе рефлексии |
| UPROPERTY() | Поле | Показ в редакторе, сохранение, защита от сборщика мусора |
| UFUNCTION() | Функцию | Вызов из Blueprint, привязка к событиям |
| GENERATED_BODY() | Тело класса | Вставляет сгенерированный движком код |
Как это выглядит
Вот класс с типичными макросами. Спецификаторы в скобках управляют поведением: EditAnywhere позволяет менять поле в редакторе, BlueprintReadWrite открывает его для Blueprint.
UCLASS()
class AEnemy : public AActor
{
GENERATED_BODY()
public:
// Поле видно и редактируется в Details
UPROPERTY(EditAnywhere, BlueprintReadWrite)
float Health = 100.0f;
// Функцию можно вызвать из Blueprint
UFUNCTION(BlueprintCallable)
void TakeDamage(float Amount);
};Спецификаторы UPROPERTY
В скобках UPROPERTY указывают, как поле ведёт себя в редакторе:
EditAnywhere— можно менять в редакторе у любого экземпляра.VisibleAnywhere— видно, но только для чтения.BlueprintReadWrite— Blueprint может читать и писать.Category="Stats"— группирует поле в Details под заголовком.
Как работает под капотом
Перед компиляцией C++ запускается Unreal Header Tool (UHT). Он читает заголовки, находит макросы и генерирует дополнительный C++-код — таблицы рефлексии, описывающие каждое помеченное поле и функцию. Именно поэтому GENERATED_BODY() обязателен: на его место подставляется этот сгенерированный код. Без UHT и макросов класс остался бы обычным C++ без интеграции с движком.
Частые ошибки
- Забыть UPROPERTY у указателя на объект. Тогда сборщик мусора может удалить объект, и указатель повиснет — частая причина крашей.
- Пропустить GENERATED_BODY(). Класс не скомпилируется.
- Неверные спецификаторы. Например, ждать поле в редакторе, забыв EditAnywhere.
Спецификаторы UFUNCTION
У функций тоже есть спецификаторы, открывающие их движку по-разному. BlueprintCallable делает функцию вызываемой как нода в блюпринте — так C++-логику дёргают из визуального графа. BlueprintImplementableEvent объявляет в C++ событие, тело которого пишется уже в блюпринте: код говорит «здесь что-то происходит», а художник решает, что именно. BlueprintNativeEvent — гибрид: есть реализация по умолчанию в C++, но её можно переопределить в блюпринте.
Эти спецификаторы — мост между двумя мирами. Они позволяют программисту заложить точки расширения, в которых дизайнер дополнит поведение визуально. Без них C++ и блюпринты жили бы в изоляции; благодаря им они образуют единый организм, где каждая сторона делает то, что ей удобнее.
Итоги
- Макросы включают систему рефлексии — движок узнаёт структуру классов на лету.
- UCLASS, UPROPERTY, UFUNCTION, GENERATED_BODY — обязательная основа Unreal-C++.
- Спецификаторы в скобках управляют видимостью в редакторе и Blueprint.
- Unreal Header Tool генерирует код рефлексии перед компиляцией.