文档地址:https://docs.unrealengine.com/zh-CN/Programming/Introduction/index.html
文档详细介绍了C++编程的基础,一些宏和常用变量,做下总结
(一)文档一开始介绍了Actor继承类编程的一些相关知识,以及一些有关UPROPERTY和UFUNCTION相关的简单介绍,之后简单介绍了蓝图。
(二)之后就是深入介绍
主要的类是四种,UObject,AActor,UActorComponnnet,UStruct。
(1)UObject是最基本的构建块,结合UClass可以提供反射、序列化、垃圾回收、联网。每个UObject都会创建一个UClass。我的理解是,UClass对UObject的梳理进行管理,并且提供序列化和联网等功能。
(2)AActor是非常重要的一种类型,可以直接放在舞台上的所有对象都是从其扩展而来,AActor继承自UObject,同时AActor有一些特殊的函数,BeginPlay()在对象首次存在是调用,Tick()每帧调用一次,EndPlay()在对象离开Gameplay空间时调用。
UWorld::SpawnActor()BeginPlay()Tick()。
使用时使用GetWorld()->SpawnActor<T>(),使用这个函数偶尔会出现编辑器崩溃,以后需要关注类似问题。
(3)UActorComponent
(4)UStruct,不会被垃圾回收
(三)虚幻反射系统
GamePlay类利用特殊标记实现反射功能,反射功能可以实现动态功能,例如GC、序列化、网络复制和BP/C++通信。简要标记概述:
UCLASS():为结构体生成反射数据,结构体必须派生自UObject
USTRUCT()生成反射,不需要派生自UObject
GENERATED_BODY()UE4替换为相关的生成代码
UPROPERTY:变量
UFUNCTION:方法
示例
#include "MyObject.generated.h" UCLASS(Blueprintable) class UMyObject : public UObject { GENERATED_BODY() public: MyUObject(); UPROPERTY(BlueprintReadOnly, EditAnywhere) float ExampleProperty; UFUNCTION(BlueprintCallable) void ExampleFunction(); };
-
Blueprintable
-
BlueprintReadOnly
-
EditAnywhere
-
Category
-
BlueprintCallable
(四)迭代器介绍
对象迭代器:迭代特定类型的UObject及其子类
// 查找所有当前UObject实例,不包括子类 for (TObjectIterator<UObject> It; It; ++It) { UObject* CurrentObject = *It; UE_LOG(LogTemp, Log, TEXT("Found UObject named:%s"), *CurrentObject->GetName()); } //包括子类 for (TObjectIterator<UMyClass> It; It; ++It) { // ... }
AActor也有自己的迭代器,
APlayerController* MyPC = GetMyPlayerControllerFromSomewhere(); UWorld* World = MyPC->GetWorld(); // 正如对象迭代器一样,您可以提供一个具体类来仅获得 // 属于该类或派生自该类的对象 for (TActorIterator<AEnemy> It(World); It; ++It) { // ... }
(五)垃圾回收
UE4使用反射系统实现垃圾回收,继承自UObject的物体会实现自动垃圾回收,当没有有效引用的时候会实现垃圾回收。
void CreateDoomedObject() { MyGCType* DoomedObject = NewObject<MyGCType>(); }
函数运行完成之后临时变量无引用,会在下一次垃圾清理的时候触发GC。
AActor只有在手动调用Destroy函数时才会在下一次GC时被销毁。
UStruct不参与GC。
继承FGCObject参与GC。
(六)字符串
FString类型字符串需要TEXT()宏创建。用途类似于std::String
FText使用NSLOCTEXT创建
FName使用字典处理,速度较快
主要包括TArray、TMap、TSet
TArray类似vector,TMap是键值对的集合,TSet是唯一值集合。
容器迭代器:
void RemoveDeadEnemies(TSet<AEnemy*>& EnemySet) { // 从集开头处开始,迭代至集末尾 for (auto EnemyIterator = EnemySet.CreateIterator(); EnemyIterator; ++EnemyIterator) { // *运算符获取当前元素 AEnemy* Enemy = *EnemyIterator; if (Enemy.Health == 0) { //“RemoveCurrent”受TSet和TMap支持 EnemyIterator.RemoveCurrent(); } } } // 将迭代器向后移动一个元素 --EnemyIterator; // 将迭代器向前/向后移动一定偏移量,这里的偏移量是个整数 EnemyIterator += Offset; EnemyIterator -= Offset; // 获取当前元素的索引 int32 Index = EnemyIterator.GetIndex(); // 将迭代器复位到第一个元素 EnemyIterator.Reset();
// TArray TArray<AActor*> ActorArray = GetArrayFromSomewhere(); for (AActor* OneActor :ActorArray) { // ... } // TSet――与TArray相同 TSet<AActor*> ActorSet = GetSetFromSomewhere(); for (AActor* UniqueActor :ActorSet) { // ... } // TMap――迭代器返回键-值对 TMap<FName, AActor*> NameToActorMap = GetMapFromSomewhere(); for (auto& KVP :NameToActorMap) { FName Name = KVP.Key; AActor* Actor = KVP.Value; // ... }