Unreal EngineMiddleTechnical
Что такое макросы UPROPERTY и UFUNCTION и какие параметры они поддерживают?
UPROPERTY регистрирует поле для GC, редактора, Blueprint и сериализации; UFUNCTION регистрирует метод для Blueprint, RPC и рефлексии. Оба поддерживают десятки параметров-спецификаторов, управляющих видимостью и поведением.
Макрос UPROPERTY
UPROPERTY сообщает системе рефлексии UE о поле класса. Без него GC не видит указатель на UObject, поле не появляется в редакторе и не сериализуется.
Спецификаторы UPROPERTY
- EditAnywhere — редактируется в экземплярах и Blueprint-дефолтах.
- EditDefaultsOnly — только в CDO (Class Default Object), не в экземплярах.
- EditInstanceOnly — только в размещённых экземплярах.
- VisibleAnywhere / VisibleDefaultsOnly — показать без редактирования.
- BlueprintReadWrite / BlueprintReadOnly — доступность в Blueprint-графах.
- Replicated — реплицировать по сети клиентам.
- ReplicatedUsing=OnRep_FieldName — вызвать функцию при получении репликации.
- Transient — не сериализовать (не сохранять в .uasset / сейв-файл).
- SaveGame — включить в сейв через
USaveGame. - Config — читать значение из .ini файла.
- Category="Name" — группировка в деталях редактора.
UCLASS()
class AMyCharacter : public ACharacter
{
GENERATED_BODY()
public:
// Редактируется везде, доступно в BP, реплицируется
UPROPERTY(EditAnywhere, BlueprintReadWrite, Replicated, Category="Stats")
float Health = 100.f;
// Только в дефолтах, только чтение в BP
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Config")
float MaxHealth = 100.f;
// Реплицированное с callback
UPROPERTY(ReplicatedUsing=OnRep_Health)
float SyncedHealth;
UFUNCTION()
void OnRep_Health();
// Не сохраняется, не сериализуется
UPROPERTY(Transient)
UParticleSystemComponent* SpawnFX;
};
Макрос UFUNCTION
UFUNCTION регистрирует метод в системе рефлексии: Blueprint может его вызвать, система сети генерирует RPC-обёртки, рефлексия позволяет вызывать по имени.
Спецификаторы UFUNCTION
- BlueprintCallable — вызываемая из BP нода с execution pin.
- BlueprintPure — без side-effect, нет execution pin (как геттер).
- BlueprintImplementableEvent — объявлена в C++, реализуется в BP.
- BlueprintNativeEvent — реализация по умолчанию в C++ (
_Implementation), переопределяемая в BP. - Server, Reliable/Unreliable — RPC, выполняется на сервере.
- Client, Reliable/Unreliable — RPC, выполняется на клиенте-владельце.
- NetMulticast, Reliable/Unreliable — RPC на всех клиентах и сервере.
- CallInEditor — кнопка вызова прямо из деталей редактора.
- Exec — вызов из консоли командой имя функции.
UCLASS()
class AMyPlayerController : public APlayerController
{
GENERATED_BODY()
public:
// Вызов из BP
UFUNCTION(BlueprintCallable, Category="Input")
void StartSprinting();
// Геттер в BP без execution pin
UFUNCTION(BlueprintPure, Category="Stats")
float GetHealthPercent() const { return Health / MaxHealth; }
// RPC: клиент вызывает на сервере
UFUNCTION(Server, Reliable)
void ServerFire(FVector_NetQuantize Origin, FVector_NetQuantize Direction);
// Реализация RPC (обязательный суффикс _Implementation)
void ServerFire_Implementation(
FVector_NetQuantize Origin, FVector_NetQuantize Direction);
// Событие BP реализует — C++ только объявляет
UFUNCTION(BlueprintImplementableEvent, Category="Events")
void OnLevelUp(int32 NewLevel);
// Консольная команда: MyExecCmd в консоли
UFUNCTION(Exec)
void MyExecCmd();
private:
float Health = 100.f;
float MaxHealth = 100.f;
};
Подводные камни
- BlueprintCallable на const-методе без BlueprintPure: const-метод в BP появится с execution pin; если нет side-effect — добавьте
BlueprintPureдля чистого геттера. - Отсутствие _Implementation у RPC: компилятор UHT генерирует декларацию
_Implementation, но если вы её не определите — ошибка линковки с нечитаемым сообщением. - Replicated без GetLifetimeReplicatedProps: каждое поле с
Replicatedтребует записи вGetLifetimeReplicatedPropsчерезDOREPLIFETIME; без этого поле не реплицируется и нет предупреждения. - EditAnywhere на массиве UObject-указателей без UPROPERTY GC-спецификатора: поле и так попадает в GC через UPROPERTY, но если указатель не в UPROPERTY — редактор может отображать ссылку, а GC всё равно уничтожит объект.
- Config без ini-раздела: поле с
Configчитает из ini только если в UCLASS указанConfig=Game(или другой ini-файл); без этого значение игнорируется. - BlueprintImplementableEvent без реализации в BP: если BP-субкласс не реализовал событие, вызов из C++ просто ничего не делает — нет предупреждения в рантайме.
- UFUNCTION(Exec) на не-APlayerController: Exec работает только на APlayerController, ACheatManager, AGameMode и AGameState; на других классах команда не регистрируется в консоли.
Common mistakes
- Объяснять UPROPERTY и UFUNCTION только по синтаксису, без жизненного цикла и стоимости.
- Игнорировать ошибки, null/empty состояния, порядок инициализации или режим сборки.
- Давать пример, который работает в демо, но ломается при изменении владельца ресурса.
- Использовать макросы или specifier-и наугад и забывать про UObject GC.
What the interviewer is testing
- Кандидат формулирует точную модель для UPROPERTY и UFUNCTION, а не только определение.
- Пример компилируем, безопасен по lifetime и соответствует версии технологии.
- Названы trade-off, ограничения и диагностируемые симптомы ошибки.
- Понимает границу между C++ кодом, runtime/framework metadata и editor/UI слоем.