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);
相关推荐
波波00710 分钟前
每日一题:请解释.NET 中的泛型约束是什么
java·面试·.net
清风徐来QCQ21 分钟前
redis 面试可能会问的问题
数据库·redis·面试
小江的记录本22 分钟前
【Spring Boot】Spring Boot 全体系知识结构化拆解(附 Spring Boot 高频面试八股文精简版)
java·spring boot·后端·spring·面试·tomcat·mybatis
ssshooter24 分钟前
infer,TS 类型系统的手术刀
前端·面试·typescript
我叫黑大帅29 分钟前
Js常用数组处理
前端·javascript·面试
我叫黑大帅32 分钟前
Js常用的字符串处理
前端·javascript·面试
gustt33 分钟前
手写 Zustand:从零实现 React 轻量级状态管理库
前端·面试
红云梦36 分钟前
用大模型生成结构化面试评估报告:Prompt工程实战
ai·面试·职场和发展·prompt
程序员爱钓鱼37 分钟前
GoWeb开发核心库: net/http深度指南
后端·面试·go
野犬寒鸦38 分钟前
JVM垃圾回收机制深度解析(G1篇)(垃圾回收过程及专业名词详解)(补充)
java·服务器·开发语言·jvm·后端·面试