Garbage collection:垃圾收集 Reference updating:引用自动更新 Reflection:反射 Serialization:序列化 Automatic updating of default property changes:自动检测默认变量的更改 Automatic property initialization:自动变量初始化 Automatic editor integration:和虚幻引擎编辑器的自动交互 Type information available at runtime:运行时类型识别 Network replication:网络复制 主要: + [[C++API/反射系统|反射系统]] + 内存管理、垃圾回收 + 序列化模型、SaveGame + Class Default Object CDO 类默认对象 + 编辑器可见 + 元数据 UClass SubClassOf<> + 网络同步 UObject 虚幻对象 Object Actor ActorComponent UStruct 从UObject派生的子类,都会创建一个UClass UClass会包含该类所有的元数据(代码中定义的类型、成员以及代码中引用的类型和成员) UObject 和 UClass 处于对象生命周期的最根部。 UClass在描述UObject创建的实例的样子,提供了可序列化的联网等功能 [[反射系统]]: + UCLASS:生成反射数据,前提是类必须是UObject + USTRUCT:生成反射数据 + UPROPERTY:变量的网络复制,序列化,蓝图访问等,GC调用,获取UObject的引用次数 + UFUNCTION:蓝图调用函数,RP等 + GENERATED_BODY():在类的最开始的位置 最下方的头文件:`#include "类名.generated.h"` # UObject 和 垃圾回收 垃回程ll序中维护了一个**根集**, 根集存储着一堆对象,GC不会回收的对象都存储在根集中, 在根集中,某个对象到一个对象存在引用路径,就不会对其进行垃圾回收 如果某个对象不存在到根集的路径,则认为无法访问,GC会在下次执行时将其回收(删除) 引擎的GC是按照固定时间间隔来运行程序 UPROPERTY 和 容器(TArray,TMap,TSet)中存储的UObject\* 指针都被当做是垃圾回收引用 纯C++类: FGCObject 重写纯虚函数:`AddReferencedObjects(FReferenceCollector& Collector)` # UObject 类默认对象 UClass TsubClassOf CDO UClass:保存着反射数据 或者 保存着一个类的各种信息 TsubClass UClass的模板类 CDO 类默认对象,Class Default Object 每个继承于UObject的类都有CDO 记录了初始的信息 获取UClass的函数:GetClass() 成员函数 StaticClass() 静态函数 然后通过UClass->GetDefaultObject() 在纯C++中工作时: 1. 使用对象的`GetClass()`成员函数和该对象类的`StaticClass()`静态成员函数,两者都会返回相同的`UClass`指针。这是因为该对象是直接由其C++类实例化的,没有任何派生的蓝图类存在。 但当您使用C++类作为蓝图的基类时,情况就会变得有些复杂: 2. 当您在编辑器中从C++基类创建蓝图,您实际上是在创建该基类的子类。这个新的子类是蓝图生成的,并且包含了蓝图中定义的任何额外的逻辑和数据。因此,这个蓝图实际上是您的C++类的一个派生类。 3. 当您实例化这个蓝图,`GetClass()`会返回这个特定蓝图的`UClass`,因为您实际上是在实例化该蓝图类,而不是原始的C++基类。 4. 然而,当您在这个蓝图对象上调用`StaticClass()`时,由于这是一个静态方法,它实际上是基类上的方法,所以它返回的是C++基类的`UClass`。 这就是为什么在创建了基于C++基类的蓝图后,这两个函数的返回值会不同:`GetClass()`返回的是实际蓝图的`UClass`,而`StaticClass()`返回的是C++基类的`UClass`。 这种设计允许Unreal Engine在C++和蓝图之间进行无缝的交互,同时保留了C++的类型信息和蓝图的扩展性。 > UClass 不仅需要记录类型信息,还需要承担序列化工作,数据也需要记录 # UObject 查找(迭代器) ```cpp void AMyActorForLearn::LearnFunc_FindObject() { #if 0 //查找世界的UObject for(TObjectIterator<UObject> It;It;++It) { UObject* Current = *It; UKismetSystemLibrary::PrintString(GetWorld(),Current->GetName()); }#endif //查找世界中的AActor for(TActorIterator<AActor> It(GetWorld(),GetClass());It;++It) { auto Current = *It; UKismetSystemLibrary::PrintString(GetWorld(),Current->GetName()); } //根据类获取Actor auto Actor = UGameplayStatics::GetActorOfClass(GetWorld(),GetClass()); UKismetSystemLibrary::PrintString(GetWorld(),Actor->GetName()); //根据标签获取Actor //UGameplayStatics::GetAllActorsWithTag(); //UGameplayStatics::GetAllActorsOfClassWithTag();} ```