Unreal Engine
反射宏
初步学习反射宏,记录内容,主要是一些基础
================================================================================
UE4 反射系统三大宏 总结笔记
================================================================================
一、核心概念:什么是反射系统?
--------------------------------------------------------------------------------
UE4 在标准 C++ 之上构建了一套反射系统(Reflection System),让引擎在
运行时能“知道”一个类有哪些属性、哪些方法。
你写的 UCLASS / UPROPERTY / UFUNCTION 宏,就是在向引擎登记:
“这个类 / 属性 / 函数,请纳入你的管理。”
编译前,Unreal Header Tool (UHT) 会扫描这些宏,自动生成包含类型信息、
序列化、网络复制等功能的“元代码”,和你的纯 C++ 逻辑缝合在一起。
这就是你在编辑器中能编辑数值、在蓝图中能连线调用函数、在网络上能自动
同步数据的根本原因。
================================================================================
二、UCLASS() —— 登记一个类
--------------------------------------------------------------------------------
【作用】
放在类声明上方,告诉引擎:这个类可以被反射管理。
【常见说明符】
Blueprintable 允许从这个 C++ 类创建蓝图子类
BlueprintType 允许把该类的实例作为蓝图变量
Abstract 抽象类,不能直接在关卡里放置实例
NotBlueprintable 禁止创建蓝图子类
ClassGroup=… 在新建类向导里分组
【留空的后果】
不报错,但默认是 NotBlueprintable(不能创建蓝图子类)。
不过部分父类(如 UGameInstance)内部标记了 IsBlueprintBase=true,
子类会继承这个许可,所以留空也可能“碰巧”能创建蓝图子类。
→ 绝对不要依赖默认行为,需要被蓝图继承就显式写 Blueprintable。
【示例】
UCLASS(Blueprintable, Abstract)
class NETTEST_API UMyBaseActor : public AActor
{
GENERATED_BODY()
};
================================================================================
三、UPROPERTY() —— 登记一个成员变量
--------------------------------------------------------------------------------
【作用】
放在成员变量声明前,让该变量拥有引擎特性,包括:
- 在编辑器中可见 / 可编辑
- 在蓝图中可读写
- 参与网络复制
- 参与序列化(保存、加载)
【常见说明符】(可组合使用)
EditAnywhere 编辑器中任何地方都可编辑
EditDefaultsOnly 只在类的默认值设置中可编辑
EditInstanceOnly 只在关卡中放置的实例上可编辑
VisibleAnywhere 编辑器中可见但不可编辑
BlueprintReadOnly 蓝图可读,不可写
BlueprintReadWrite 蓝图可读写
Category = ”…” 在细节面板中归类显示
Replicated 参与网络复制(须配合 GetLifetimeReplicatedProps)
Transient 不参与序列化(临时数据)
【留空的后果】
编译不报错,但该属性在编辑器中不可见、蓝图中不可读写,等于白写。
【示例】
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = “Stats”)
float Health;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Replicated)
int32 KillCount;
================================================================================
四、UFUNCTION() —— 登记一个成员函数
--------------------------------------------------------------------------------
【作用】
放在函数声明前,让该函数拥有引擎特性,包括:
- 被蓝图调用或重写
- 成为网络 RPC(Server / Client / NetMulticast)
【极常用说明符】
BlueprintCallable 蓝图可调用
BlueprintImplementableEvent 蓝图实现(C++ 只声明,不实现)
BlueprintNativeEvent C++ 提供默认实现,蓝图可重写
Server RPC:客户端调用,服务器执行
Client RPC:服务器调用,拥有者客户端执行、
NetMulticast RPC:服务器调用,所有客户端执行
WithValidation 配合 Server,需要实现验证函数防作弊
Reliable 可靠 RPC(保证送达,必须与 Server/Client 一起用)
Unreliable 不可靠 RPC(不保证送达)
Category = ”…” 在蓝图右键菜单中归类
【留空的后果】
编译不报错,但蓝图右键菜单里完全找不到该函数,只能作为 C++ 内部函数使用。
【示例】
UFUNCTION(BlueprintCallable, Category = “Combat”)
void Attack();
UFUNCTION(Server, Reliable, WithValidation)
void ServerAttack();
================================================================================
五、核心法则总结
--------------------------------------------------------------------------------
1. 加宏就是在“贴标签”,告诉引擎你需要什么能力。
2. 宏的括号留空 = 放弃对应功能,不会报错但几乎什么都做不了。
3. UPROPERTY 和 UFUNCTION 绝对不能留空,否则编辑器/蓝图无法使用。
4. UCLASS 需要蓝图继承就必须显式写 Blueprintable,别依赖父类的默认许可。
5. GENERATED_BODY() 和 .generated.h 是反射系统的入口,一个都不能少。
================================================================================