UE5核心宏标记 (UCLASS, UPROPERTY, UFUNCTION) 学习笔记

Unreal Engine 使用一套自省的反射系统,它允许程序在运行时查询、访问和操作类、变量和函数的信息。然而,标准的 C++ 本身并不支持这种级别的反射。

这些宏标记(如 UCLASS(), UPROPERTY(), UFUNCTION())的作用就是为 Unreal Header Tool (UHT) 提供指令。UHT 在编译前扫描你的代码,根据这些标记生成额外的反射代码(*.generated.h 文件),从而将你的 C++ 代码"暴露"给 UE 的各个系统,如蓝图编辑器、序列化、网络复制和垃圾回收。


一、UCLASS() - 类标记

作用:将一个 C++ 类声明为 UE 可识别的、可参与引擎对象管理的 UObject。

必须包含 :在标记了 UCLASS() 的类体内,必须包含 GENERATED_BODY() 宏。

常用选项 (Specifiers)

选项 说明 使用场景
Blueprintable 最重要选项之一。允许此类的蓝图被创建。 希望设计师能基于你的 C++ 类创建蓝图。
NotBlueprintable (默认)禁止创建此类的蓝图。 不希望被蓝图继承的基类或工具类。
BlueprintType 允许此类作为变量类型在蓝图中使用。 希望蓝图能定义此类型的变量。
Placeable 允许在关卡编辑器中将此类的 Actor 拖入场景。 大多数继承自 AActor 的类。
NotPlaceable (默认)禁止在关卡中放置。 抽象基类或不应直接放置的类(如 AGameMode)。
Abstract 标记该类为抽象类,无法创建实例。 用于定义接口或基础功能的基类。

示例代码:

cpp 复制代码
// 这个类可以被蓝图继承,可以在蓝图中用作变量类型,并且可以放置在关卡中
UCLASS(Blueprintable, BlueprintType, Placeable)
class AMyGameCharacter : public ACharacter
{
    GENERATED_BODY() // 必须包含在类体内
    // ... 类的成员
};

二、UPROPERTY() - 变量标记

作用:暴露变量给属性系统,使其可被编辑器详情面板显示、被蓝图访问、参与网络复制、序列化等。

常用选项 (Specifiers) - 按功能分类

1. 访问与可见性 (Access & Visibility)

选项 说明 建议
BlueprintReadOnly 蓝图可读,不可修改。 最常用、最安全。在 C++ 中设置,供蓝图使用。
BlueprintReadWrite 蓝图可读也可写。 谨慎使用!蓝图可能在任何时候修改它。
VisibleAnywhere 在编辑器的详情面板可见但不可编辑 用于显示状态信息(如计算后的结果)。
EditAnywhere 详情面板可见且可编辑 可在类默认值和实例上修改。灵活性高,但控制力弱。
EditDefaultsOnly 仅在类的蓝图默认值中可编辑,实例上不可编辑。 最常用。用于定义类的固有属性(如最大血量、速度)。
VisibleDefaultsOnly 仅在类的蓝图默认值中可见,不可编辑。 -
EditInstanceOnly 仅在关卡中的实例上可编辑,默认值中不可编辑。 用于每个实例都不同的属性(如 NPC 的名字)。

2. 游戏性功能 (Gameplay)

选项 说明 注意
Replicated 启用网络复制。服务器端变量的变化会自动同步到客户端。 多人游戏核心。需在 GetLifetimeReplicatedProps 中声明。
SaveGame 此变量应被包含在游戏存档/读档过程中。 需与 USaveGame 系统配合使用。
Transient 临时变量,不被保存或加载。 用于运行时计算的缓存或临时指针。

3. 其他 (Others)

选项 说明
AdvancedDisplay 在详情面板中,该属性将被折叠到"高级"部分。
Category = "CategoryName" 重要:将属性归类到详情面板的特定分类下,使UI更整洁。

示例代码:

cpp 复制代码
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Health", Replicated)
//    ^^^^^^^^^^^^^^^^^^^  ^^^^^^^^^^^^^^^^      ^^^^^^^^  ^^^^^^^^^
//    仅在默认值可编辑      蓝图只读(安全)      分类目录    网络复制
int32 MaxHealth;

UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Health")
//    ^^^^^^^^^^^^^^^^  ^^^^^^^^^^^^^^^^
//    在任何地方可见(只读)  蓝图只读
int32 CurrentHealth;

UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stats")
//    ^^^^^^^^^^^^^  ^^^^^^^^^^^^^^^^^^
//    任何地方可编辑   蓝图可读写(谨慎!)
float MovementSpeed;

三、UFUNCTION() - 函数标记

作用:暴露函数给蓝图系统或引擎回调机制(如定时器、委托)。

常用选项 (Specifiers)

1. 蓝图调用 (Blueprint Callability)

选项 说明 蓝图中的表现
BlueprintCallable 蓝图可以调用此函数来执行某些逻辑。 执行 引脚(>)。
BlueprintPure 蓝图可以调用此函数,但它不修改对象状态(无副作用) 没有执行引脚,只有输出引脚。用于计算和获取值。

2. 蓝图重写 (Blueprint Overriding)

选项 说明 C++ 实现要求
BlueprintImplementableEvent 这是一个事件,其实现完全由蓝图提供。C++ 中只有声明,无函数体。 无需在 C++ 中编写函数体。
BlueprintNativeEvent 这是一个事件,C++ 提供默认实现,但蓝图可以重写它。 必须编写一个 函数名_Implementation 作为默认实现。

3. 网络 (Networking) - RPC (Remote Procedure Call)

选项 说明 调用规则
Server 标记函数在服务器上执行。 从客户端调用,在服务器上执行。
Client 标记函数在客户端上执行。 从服务器调用,在所有客户端上执行。
NetMulticast 标记函数在所有客户端和服务器上执行。 从服务器调用,在服务器和所有客户端上执行。

示例代码:

cpp 复制代码
// 蓝图可以调用这个函数
UFUNCTION(BlueprintCallable, Category = "Combat")
void ApplyDamage(float DamageAmount);

// 这是一个纯函数,用于计算,不改变状态
UFUNCTION(BlueprintPure, Category = "Combat")
float CalculateFinalDamage(float BaseDamage) const;

// 蓝图可实现事件。C++中无实现,由蓝图定义逻辑
UFUNCTION(BlueprintImplementableEvent, Category = "Events")
void OnPlayerDied();

// 蓝图可原生事件。C++中有默认实现(_Implementation),蓝图可重写
UFUNCTION(BlueprintNativeEvent, Category = "Events")
void OnHealthChanged(float NewHealth);
// 必须提供默认实现:
virtual void OnHealthChanged_Implementation(float NewHealth);
相关推荐
沐怡旸2 小时前
【底层机制】std::shared_ptr解决的痛点?是什么?如何实现?如何正确用?
c++·面试
Java中文社群2 小时前
有点意思!Java8后最有用新特性排行榜!
java·后端·面试
moisture2 小时前
CUDA常规知识点
后端·面试
zcychong2 小时前
ArrayMap、SparseArray和HashMap有什么区别?该如何选择?
android·面试
小高0073 小时前
🌐ES6 这 8 个隐藏外挂,知道 3 个算我输!
前端·javascript·面试
甜瓜看代码4 小时前
Android事件分发机制
面试
李重楼4 小时前
前端性能优化之 HTTP/2 多路复用
前端·面试
lecepin5 小时前
AI Coding 资讯 2025-09-17
前端·javascript·面试
闰五月7 小时前
JavaScript作用域与作用域链详解
前端·面试