虚幻引擎5-Unreal Engine笔记之Qt与UE中的Meta和Property
虚幻引擎5-Unreal Engine笔记之Qt与UE中的Meta和Property
code review!
文章目录
- 虚幻引擎5-Unreal Engine笔记之Qt与UE中的Meta和Property
- 1.Qt 中的 Meta(元对象系统)
- 1.1 主要功能
- 1.2 如何实现
- 1.2.1 例子
- 1.2.2 访问 meta 信息
- 2.UE5 中的 Meta(元数据)
- 2.1 主要功能
- 2.2 使用方式
- 2.2.1 常用 meta 参数
- 2.2.2 作用
- 2.3 总结对比
- 3.Meta 是否是一个 Map?
- 3.1 Qt 的 Meta(元对象系统)是不是 Map?
- 3.1.1 详细说明
- 3.1.2 可以这样理解
- 3.1.3 举个例子
- 3.2 UE5 的 Meta(元数据参数)是不是 Map?
- 3.2.1 详细说明
- 3.2.2 举个例子
- 3.2.3 总结
- 3.3 结论对比
- 3.3.1 总结一句话
- 4.Qt 和 UE5 中的 Property
- 4.1 Qt 中的 Property
- 4.1.1 作用
- 4.1.2 声明方式
- 4.1.2.1 解释
- 4.1.3 使用场景
- 4.1.4 访问方法
- 4.2 UE5 中的 Property
- 4.2.1 作用
- 4.2.2 声明方式
- 4.2.2.1 解释
- 4.2.3 使用场景
- 4.2.4 动态访问
- 4.3 对比总结
- 4.3.1 小结
1.Qt 中的 Meta(元对象系统)
Qt 是一个 C++ 框架,广泛用于 GUI 应用开发。它的 meta 主要指的是 元对象系统(Meta-Object System)。Qt 的元对象系统让 C++ 拥有了类似于反射和运行时类型信息(RTTI)的能力,这是原生 C++ 缺少的。
1.1 主要功能
- 信号与槽(Signals & Slots)
- 运行时类型识别(RTTI)
- 属性系统(Property System)
- 动态语言特性(反射)
1.2 如何实现
Qt 使用 MOC(Meta-Object Compiler),对含有 Q_OBJECT
宏的类做预处理,生成 meta 信息。
1.2.1 例子
class MyObject : public QObject {Q_OBJECT
public:MyObject(QObject *parent = nullptr);signals:void mySignal(int value);public slots:void mySlot(int value);
};
Q_OBJECT
宏启用元对象功能- MOC 生成的代码包含元数据,比如信号和槽的注册信息
1.2.2 访问 meta 信息
MyObject obj;
const QMetaObject *metaObj = obj.metaObject();
qDebug() << metaObj->className();
2.UE5 中的 Meta(元数据)
Unreal Engine 5 是一款强大的游戏引擎。它的 meta 主要出现在 UCLASS、UPROPERTY、UFUNCTION 等宏中的 元数据参数。这些 meta 信息用于编辑器、序列化、蓝图集成等。
2.1 主要功能
- 控制属性在编辑器中的显示和行为
- 设置序列化、复制规则
- 蓝图可见性与调用权限
2.2 使用方式
用在宏参数内,例如:
UCLASS()
class AMyActor : public AActor
{GENERATED_BODY()public:// 属性元数据UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Stats", meta=(ClampMin="0.0", ClampMax="100.0"))float Health;// 函数元数据UFUNCTION(BlueprintCallable, meta=(DisplayName="Do Something"))void DoSomething();
};
2.2.1 常用 meta 参数
ClampMin
/ClampMax
:编辑器里限制数值范围DisplayName
:蓝图/编辑器中显示的名字ToolTip
:鼠标悬停时的帮助提示BlueprintReadOnly
、BlueprintReadWrite
:蓝图访问控制
2.2.2 作用
- 让设计师和程序员协同工作更高效
- 提高编辑器的可用性和自动化程度
2.3 总结对比
Qt meta(元对象系统) | UE5 meta(元数据参数) | |
---|---|---|
目的 | 运行时类型、信号槽、反射 | 编辑器、序列化、蓝图交互等 |
形式 | Q_OBJECT 宏 + MOC 生成的 meta 信息 | meta=(...) ,附加在 UCLASS/UPROPERTY 上 |
实现 | C++ 预处理器和代码生成 | 宏展开+编译器+UE反射系统 |
用途 | 信号与槽、属性、QML、动态调用 | 编辑器属性、蓝图、序列化、显示、限制等 |
3.Meta 是否是一个 Map?
3.1 Qt 的 Meta(元对象系统)是不是 Map?
不是严格意义上的 Map。
3.1.1 详细说明
Qt 的元对象系统(meta-object system)并不直接用 QMap
或 std::map
来存储元信息。Qt 通过 QMetaObject
类,把类名、属性列表、信号与槽等信息组织成一种结构化的数据(通常是静态数组和结构体)。
- 这些信息在编译阶段由 MOC(Meta-Object Compiler) 生成,保存在
QMetaObject
及相关数据结构中。 - Qt 的元信息是结构化的,并不是一个单纯的 Key-Value 映射。
3.1.2 可以这样理解
- 虽然可以通过名字查找属性(有点像 Map),但底层其实是用一种高效的数据结构(如数组+索引)来做查找。
- 例如
QMetaObject::property(int index)
或QMetaObject::indexOfProperty(const char *name)
。
3.1.3 举个例子
const QMetaObject* metaObj = obj.metaObject();
int propIndex = metaObj->indexOfProperty("myProperty");
QMetaProperty prop = metaObj->property(propIndex);
- 这里虽然可以通过名字查找,但底层不是标准的 Map,而是特定的数据结构。
3.2 UE5 的 Meta(元数据参数)是不是 Map?
它的表现形式接近 Map,但实现上是元数据表。
3.2.1 详细说明
在 Unreal Engine 5 中,meta=(...)
里的内容很像 Key-Value Map:
UPROPERTY(meta = (ClampMin = "0.0", ClampMax = "100.0"))
float Health;
- 这里的
meta
参数在语法上就是一堆键值对(Key-Value)。 - 底层实现时,UE5 会把这些参数解析成类似于
TMap<FName, FString>
的结构(即 Map),保存到FProperty
或UFunction
等对象的元数据表里。
3.2.2 举个例子
- 在运行时、编辑器里,可以通过 API 访问这些元数据:
FProperty* Property = ...;
FString ClampMinValue = Property->GetMetaData(TEXT("ClampMin"));
GetMetaData
方法就是用 Key 查 Value,非常像 Map。
3.2.3 总结
- UE5 的 meta 更接近 Map 的概念,实际上底层是用 Map 或类似的结构实现的。
3.3 结论对比
Qt meta | UE5 meta | |
---|---|---|
表现 | 结构化静态元对象,非 Map | Key-Value 对,接近 Map |
实现 | 静态数组/结构体,索引查找 | TMap/FName,确实是 Map 或类似结构 |
用法 | 通过索引/名字访问 | 通过 Key 查 Value |
3.3.1 总结一句话
- Qt 的 meta 不是 Map,而是一套结构化的元数据系统。
- UE5 的 meta 是一组 Key-Value 对,本质上就是 Map 或非常接近 Map。
4.Qt 和 UE5 中的 Property
4.1 Qt 中的 Property
4.1.1 作用
Qt 的 属性系统 是元对象系统(meta-object system)的一部分,主要用于:
- 反射(运行时获取/设置属性)
- 与 QML 绑定
- 属性动画
- 与 Designer 等工具交互
4.1.2 声明方式
属性通过 Q_PROPERTY
宏声明,通常在有 Q_OBJECT
的类中:
class MyObject : public QObject {Q_OBJECTQ_PROPERTY(int age READ age WRITE setAge NOTIFY ageChanged)
public:int age() const { return m_age; }void setAge(int a) { if (m_age != a) { m_age = a; emit ageChanged(); } }
signals:void ageChanged();
private:int m_age;
};
4.1.2.1 解释
Q_PROPERTY(type name READ getter WRITE setter NOTIFY signal)
- 让属性能被 Qt 的元对象系统识别和操作
4.1.3 使用场景
- 运行时反射
- QML 绑定(如在 QML 脚本中直接使用 C++ 对象的属性)
- 属性动画、序列化、编辑器支持
4.1.4 访问方法
可以通过 QMetaObject
动态读取/设置属性:
MyObject obj;
obj.setProperty("age", 30);
int age = obj.property("age").toInt();
这些方法实际上是通过 QMetaProperty 查找属性信息。
4.2 UE5 中的 Property
4.2.1 作用
在 Unreal Engine 5 中,property
通常指 UProperty 系统(现在叫 FProperty),用于:
- 反射(运行时获取/设置属性)
- 编辑器可见性和编辑
- 蓝图集成
- 网络复制
- 序列化
4.2.2 声明方式
通过 UPROPERTY
宏声明:
UCLASS()
class AMyActor : public AActor
{GENERATED_BODY()
public:UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Stats")int32 Health;
};
4.2.2.1 解释
UPROPERTY
后面加各种修饰参数,决定属性在编辑器、蓝图、网络等方面的行为
4.2.3 使用场景
- 让属性在编辑器里可见和可编辑
- 蓝图访问和修改
- 网络同步
- 序列化和保存
4.2.4 动态访问
可以通过反射 API 访问属性:
UProperty* Prop = FindField<UProperty>(AMyActor::StaticClass(), TEXT("Health"));
void* ValuePtr = Prop->ContainerPtrToValuePtr<void>(ActorInstance);
int32 HealthValue = CastField<UIntProperty>(Prop)->GetPropertyValue(ValuePtr);
属性的元数据(如 EditAnywhere
,Category
)也是通过反射系统存储和查询的。
4.3 对比总结
Qt property | UE5 property (UPROPERTY) | |
---|---|---|
作用 | 反射、QML、动画、工具 | 反射、编辑器、蓝图、网络、序列化 |
声明方式 | Q_PROPERTY 宏 | UPROPERTY 宏 |
关联系统 | 元对象系统(MOC) | 反射系统(UHT/UE4元数据表) |
运行时动态访问 | 支持(property/setProperty) | 支持(FindField, Get/Set API) |
编辑器交互 | 支持(Qt Designer/QML) | 支持(UE编辑器/蓝图) |
元数据(meta) | 附加在 Q_PROPERTY 上 | 附加在 UPROPERTY 上 |
网络复制 | 不直接支持 | 支持(Replicated等修饰符) |
4.3.1 小结
- Qt 的
property
更偏向于 GUI、QML 绑定和动画等场景。 - UE5 的
property
是游戏引擎数据驱动、编辑器交互、蓝图、网络同步等核心的基础设施。 - 两者都是“反射型属性”,都可以运行时通过名字动态访问,但用法和场景大不相同。