虚幻引擎中所有对象的基类都是 UObject
。而 UCLASS
宏的作用是标记 UObject
的子类, 以便 UObject 处理系统可以识别它们。引擎能通过一些额外的操作来生成代码,实现反射等操作。大致定义方法如下。
#pragma once
#include 'Object.h'
#include 'MyObject.generated.h' //自动生成,必须最后一个被include
UCLASS()
class MYPROJECT_API UMyObject : public UObject
{
GENERATED_BODY()
};
如 MyProject 希望将 UMyObject 类公开到其他模块,则需要指定 MYPROJECT_API
。
UObject 创建
UObjects 不支持构造器参数。所有的C++ UObject都会在引擎启动的时候初始化,然后引擎会调用其默认构造器。如果没有默认的构造器,那么 UObject 将不会编译。
UObject 应该仅在运行时使用 NewObject 构建,或者将 CreateDefaultSubobject 用于构造器。
方法 | 描述 |
---|---|
NewObject<class T> | 类似于new,但提供了可选参数保证了灵活性。 |
NewNamedObject<class T> | 通过允许为新实例指定一个名称以及对象标记和一个要指定为参数的模板对象,基于NewObject |
CreateDefaultSubobject<class T> | 创建一个组件或者子对象,可以提供创建子类和返回父类的方法。 |
注意:对于UObject,不要使用new运算符。因为UObject由引擎创建和销毁,以便于GC。手动new,delete可能会内存出错。
UObject提供的功能
-
垃圾回收,基于标记清除的GC
-
引用更新,标记了
UPROPERTY
或存储在虚幻引擎容器类中的UActorComponent
或AActor
引用。在销毁的时候对其引用的指针将置空。 -
反射
- 序列化,当
UObject
被序列化时,所有UProperty
值都将被自动写入或读取 - 默认属性变化自动更新,当
UClass
的 类默认对象(CDO)更改,引擎将尝试在加载类的所有实例时对这些实例应用这些更改。 - 自动属性初始化
- 自动编辑器整合,在编辑器中可编辑代码中定义的变量。
- 运行时类型信息可用
- 网络复制,用于多人游戏同步。
- 序列化,当
UObject对象标记
https://dev.epicgames.com/documentation/zh-cn/unreal-engine/creating-objects-in-unreal-engine#:~:text=%E7%94%9F%E6%88%90%E5%AE%9E%E4%BE%8B%E6%8C%87%E9%92%88%E3%80%82-,%E5%AF%B9%E8%B1%A1%E6%A0%87%E8%AE%B0,-EObjectFlags%20%E6%9E%9A%E4%B8%BE%E7%94%A8%E4%BA%8E
基本数据类型
类型 | 说明 |
---|---|
uint8 | 8位无符号 |
uint16 | 16位无符号 |
uint32 | 32位无符号 |
uint64 | 64位无符号 |
int8 | 8位有符号 |
int16 | 16位有符号 |
int32 | 32位有符号 |
int64 | 64位有符号 |
float | 单精度浮点数 |
double | 双精度浮点数 |
bool | 布尔类型 |
FString | 典型的"动态字符数组"字符串类型。类似std::string |
FName | 全局字符串表中不可变且不区分大小写的字符串的引用。 |
FText | 用于处理本地化的更可靠的字符串表示。 |
UStruct
在虚幻中,用struct声明的类被当作用于数据记录的作用,而非操作更加复杂的UObject类。
UStruct比UObject更加快速和轻量。也能使用UPROPERTY
,但是不被GC管理。不提供UFUNCTION
。
定义一个UStruct大致如下:
USTRUCT([Specifier, Specifier, ...])
struct FStructName
{
GENERATED_BODY()
};
建议
- 搭配智能指针使用UStruct
- 结构体最好用于简单数据类型。对于更复杂的操作使用
UObject
或AActor
子类来代替。 UStructs
不可以 用于复制。但是UProperty
变量 可以 用于复制
TSubclassOf
TSubclassOf 是提供 UClass 类型安全性的模板类。
/** type of damage */
UPROPERTY(EditDefaultsOnly, Category=Damage)
TSubclassOf<UDamageType> DamageType;
相比于原生的指针多态。使用TSubclassOf
可以获得编辑器上更好的支持。
还能获得 C++ 层级上的类型安全。如尝试进行不兼容 TSubclassOf 类型的相互指定,将出现编译错误。尝试指定泛型 UClass 时,它将执行一个运行时检查,以确定它可执行指定。如运行时检查失败,结果数值为 nullptr。