当前位置: 首页 > news >正文

成都电子商务平台网站制作报价seo在线教学

成都电子商务平台网站制作报价,seo在线教学,平台小程序,西安市灞桥区疫情UE4运用C和框架开发坦克大战教程笔记(十五)(第46~48集) 46. 批量加载 UClass 功能测试批量加载多个同类 UClass 资源 47. 创建单个资源对象测试加载并创建单个 UClass 资源对象 48. 创建同类资源对象 46. 批量加载 UClass 功能 逻…

UE4运用C++和框架开发坦克大战教程笔记(十五)(第46~48集)

  • 46. 批量加载 UClass 功能
    • 测试批量加载多个同类 UClass 资源
  • 47. 创建单个资源对象
    • 测试加载并创建单个 UClass 资源对象
  • 48. 创建同类资源对象

46. 批量加载 UClass 功能

逻辑和批量加载同类 UObject 资源的逻辑差不多。区别在 DealClassKindLoadStack() 内,如果已经有资源率先加载完成了,那后续资源加载的途中我们想让已经加载好的资源执行额外的处理逻辑(比如让它每帧生成),我们就需要补充额外的判断条件,即判断其是否第一次生成完毕。

DDWealth.h

// 加载批量 Class
struct ClassKindLoadNode;UCLASS()
class DATADRIVEN_API UDDWealth : public UObject, public IDDMM
{GENERATED_BODY()protected:// 处理批量加载 Class 节点的方法void DealClassKindLoadStack();protected:TArray<ClassKindLoadNode*> ClassKindLoadStack;
};

DDWealth.cpp

struct ClassKindLoadNode
{// 加载句柄TSharedPtr<FStreamableHandle> WealthHandle;// 没有加载的资源TArray<FClassWealthEntry*> UnLoadWealthEntry;// 已经加载的资源的数组TArray<FClassWealthEntry*> LoadWealthEntry;// 请求对象名FName ObjectName;// 回调方法名FName FunName;// 构造函数ClassKindLoadNode(TSharedPtr<FStreamableHandle> InWealthHandle, TArray<FClassWealthEntry*> InUnLoadWealthEntry, TArray<FClassWealthEntry*>& InLoadWealthEntry, FName InObjectName, FName InFunName){WealthHandle = InWealthHandle;UnLoadWealthEntry = InUnLoadWealthEntry;LoadWealthEntry = InLoadWealthEntry;ObjectName = InObjectName;FunName = InFunName;}
};void UDDWealth::WealthTick(float DeltaSeconds)
{DealClassKindLoadStack();
}void UDDWealth::LoadClassWealthKind(FName WealthKind, FName ObjectName, FName FunName)
{TArray<FClassWealthEntry*> WealthEntryGroup = GetClassKindEntry(WealthKind);// 如果数量为 0if (WealthEntryGroup.Num() == 0) {DDH::Debug() << ObjectName << " Get Null WealthKind : " << WealthKind << DDH::Endl();return;}// 判断资源可用性for (int i = 0; i < WealthEntryGroup.Num(); ++i) {if (!WealthEntryGroup[i]->WealthPtr.ToSoftObjectPath().IsValid()) {DDH::Debug() << ObjectName << " Get Not Valid in Kind : " << WealthKind << " For Name : " << WealthEntryGroup[i]->WealthName << DDH::Endl();return;}}// 未加载资源序列TArray<FClassWealthEntry*> UnLoadWealthEntry;// 已加载资源序列TArray<FClassWealthEntry*> LoadWealthEntry;// 分类保存for (int i = 0; i < WealthEntryGroup.Num(); ++i) {if (WealthEntryGroup[i]->WealthClass)LoadWealthEntry.Push(WealthEntryGroup[i]);elseUnLoadWealthEntry.Push(WealthEntryGroup[i]);}// 判断所有资源是否都已经加载if (UnLoadWealthEntry.Num() == 0) {// 填充参数TArray<FName> NameGroup;TArray<UClass*> WealthGroup;for (int i = 0; i < LoadWealthEntry.Num(); ++i) {NameGroup.Push(LoadWealthEntry[i]->WealthName);WealthGroup.Push(LoadWealthEntry[i]->WealthClass);}// 返回资源给请求对象BackClassWealthKind(ModuleIndex, ObjectName, FunName, NameGroup, WealthGroup);}else {// 获取未加载资源路径数组TArray<FSoftObjectPath> WealthPaths;for (int i = 0; i < UnLoadWealthEntry.Num(); ++i)WealthPaths.Push(UnLoadWealthEntry[i]->WealthPtr.ToSoftObjectPath());// 进行异步加载获取句柄TSharedPtr<FStreamableHandle> WealthHandle = WealthLoader.RequestAsyncLoad(WealthPaths);// 添加新的加载节点ClassKindLoadStack.Push(new ClassKindLoadNode(WealthHandle, UnLoadWealthEntry, LoadWealthEntry, ObjectName, FunName));}
}void UDDWealth::DealClassKindLoadStack()
{// 定义已完成加载节点序列TArray<ClassKindLoadNode*> CompleteStack;for (int i = 0; i < ClassKindLoadStack.Num(); ++i) {// 判断第一次加载完成,WealthHandle 已经加载完成,UnLoadWealthEntry 数量大于 0if (ClassKindLoadStack[i]->WealthHandle->HasLoadCompleted() && ClassKindLoadStack[i]->UnLoadWealthEntry.Num() > 0) {// 如果已经加载完成,设置未加载序列的资源指针for (int j = 0; j < ClassKindLoadStack[i]->UnLoadWealthEntry.Num(); ++j)ClassKindLoadStack[i]->UnLoadWealthEntry[j]->WealthClass = Cast<UClass>(ClassKindLoadStack[i]->UnLoadWealthEntry[j]->WealthPtr.ToSoftObjectPath().ResolveObject());// 将未加载完成序列里的资源填充到已加载资源序列ClassKindLoadStack[i]->LoadWealthEntry.Append(ClassKindLoadStack[i]->UnLoadWealthEntry);// 清空 UnLoadWealthEntryClassKindLoadStack[i]->UnLoadWealthEntry.Empty();}// 如果未加载序列为 0,说明已经加载完成if (ClassKindLoadStack[i]->UnLoadWealthEntry.Num() == 0) {// 加载 UClass 或者直接生成资源的情况来处理// 设置反射参数TArray<FName> NameGroup;TArray<UClass*> WealthGroup;for (int j = 0; j < ClassKindLoadStack[i]->LoadWealthEntry.Num(); ++j) {NameGroup.Push(ClassKindLoadStack[i]->LoadWealthEntry[j]->WealthName);WealthGroup.Push(ClassKindLoadStack[i]->LoadWealthEntry[j]->WealthClass);}// 返回资源给请求对象BackClassWealthKind(ModuleIndex, ClassKindLoadStack[i]->ObjectName, ClassKindLoadStack[i]->FunName, NameGroup, WealthGroup);// 添加该节点到已完成序列CompleteStack.Push(ClassKindLoadStack[i]);}}// 清空已完成节点for (int i = 0; i < CompleteStack.Num(); ++i) {ClassKindLoadStack.Remove(CompleteStack[i]);delete CompleteStack[i];}
}

测试批量加载多个同类 UClass 资源

接下来是验证环节,我们打算让多个 Actor 生成在场景中,并且为了让它们不会挤到一块,所以每次生成的时候将位置偏移一点。

WealthCallObject.h

public:// 回调函数UFUNCTION()void LoadKindClass(TArray<FName> BackNames, TArray<UClass*> BackWealths);public:// 生成的偏移量UPROPERTY(EditAnywhere)float OffsetValue;

WealthCallObject.cpp


void UWealthCallObject::DDLoading()
{// 测试完毕后记得注释掉LoadClassWealthKind("ViewActor", "LoadKindClass");
}void UWealthCallObject::LoadKindClass(TArray<FName> BackNames, TArray<UClass*> BackWealths)
{for (int i = 0; i < BackWealths.Num(); ++i) {DDH::Debug() << BackNames[i] << DDH::Endl();GetDDWorld()->SpawnActor<AActor>(BackWealths[i], ViewTrans.GetLocation() + FVector(OffsetValue * i, 0.f, 0.f), FQuat::Identity.Rotator());}
}

编译后,在 Blueprint 文件夹下创建一个 ViewActor 文件夹,将 ViewActor1 放进去,并复制两个,分别取名为 ViewActor2ViewActor3。给它俩换一下网格体模型。

更改网格体模型
给 PlayerData 里再配置两个 Class 资源数据:

在这里插入图片描述
打开 WealthCallObject 的蓝图,设置 Offset Value 为 150。

运行游戏,可见左上角输出了 3 个 Class 资源的名字,场景内也出现了它们的实例。

在这里插入图片描述
在第一次运行后,在 Deal{xxx}LoadStack() 方法里会给加载节点里的 UObject* / UClass* 赋值,它们就不为空了,也就不会进行异步加载,为了让它每次都像第一次运行那样(为了方便测试异步加载无误),我们要修改一下代码,让它在编辑器运行时每次都清空 WealthObject 和 WealthClass。这样就以后打包完游戏就不会自动清空。

DDWealth.cpp

void UDDWealth::WealthBeginPlay()
{for (int i = 0; i < WealthData.Num(); ++i) {// ... 省略#if WITH_EDITOR	// 循环设置 WealthObject 和 WealthClass 为空,目的在于每次从编辑器启动游戏时,资源 Asset 的状态都重置for (int j = 0; j < WealthData[i]->ObjectWealthData.Num(); ++j)WealthData[i]->ObjectWealthData[j].WealthObject = NULL;for (int j = 0; j < WealthData[i]->ClassWealthData.Num(); ++j)WealthData[i]->ClassWealthData[j].WealthClass = NULL;
#endif}
}

47. 创建单个资源对象

我们先前写的逻辑都是加载资源然后将其返回给请求者,接下来我们打算实现:加载 UClass 资源并创建对象后,将对象返回给请求者。

下图截取自梁迪老师的 DataDriven 文档:

在这里插入图片描述
创建多个对象的方法里,每帧都会创建一个对象,创建足够数量的对象后才会将所有的对象返回给请求对象。

这节课我们先实现创建单个资源对象的功能。

DDWealth.h

public:// 创建一个对象实例void BuildSingleClassWealth(EWealthType WealthType, FName WealthName, FName ObjectName, FName FunName, FTransform SpawnTransform);protected:// 生成三种资源对象的反射回调函数DDOBJFUNC_TWO(BackObject, FName, BackName, UObject*, BackObject);DDOBJFUNC_TWO(BackActor, FName, BackName, AActor*, BackActor);DDOBJFUNC_TWO(BackWidget, FName, BackName, UUserWidget*, BackWidget);

DDWealth.cpp

// 给 UClass 加载节点补充另外的内容,以便支持对象创建
struct ClassSingleLoadNode
{TSharedPtr<FStreamableHandle> WealthHandle;FClassWealthEntry* WealthEntry;FName ObjectName;FName FunName;// 生成位置FTransform SpawnTransform;// 是否只加载 UClass 资源bool IsLoadClass;ClassSingleLoadNode(TSharedPtr<FStreamableHandle> InWealthHandle, FClassWealthEntry* InWealthEntry, FName InObjectName, FName InFunName){WealthHandle = InWealthHandle;WealthEntry = InWealthEntry;ObjectName = InObjectName;FunName = InFunName;IsLoadClass = true;		// 添加}// 另一个构造函数ClassSingleLoadNode(TSharedPtr<FStreamableHandle> InWealthHandle, FClassWealthEntry* InWealthEntry, FName InObjectName, FName InFunName, FTransform InSpawnTransform){WealthHandle = InWealthHandle;WealthEntry = InWealthEntry;ObjectName = InObjectName;FunName = InFunName;SpawnTransform = InSpawnTransform;IsLoadClass = false;}
};// 给处理方法增加判断,是仅仅加载资源还是创建对象
void UDDWealth::DealClassSingleLoadStack()
{TArray<ClassSingleLoadNode*> CompleteStack;for (int i = 0; i < ClassSingleLoadStack.Num(); ++i) {if (ClassSingleLoadStack[i]->WealthHandle->HasLoadCompleted()) {ClassSingleLoadStack[i]->WealthEntry->WealthClass = Cast<UClass>(ClassSingleLoadStack[i]->WealthEntry->WealthPtr.ToSoftObjectPath().ResolveObject());// 判断是否生成对象if (ClassSingleLoadStack[i]->IsLoadClass) {// 返回资源给对象BackClassWealth(ModuleIndex, ClassSingleLoadStack[i]->ObjectName, ClassSingleLoadStack[i]->FunName, ClassSingleLoadStack[i]->WealthEntry->WealthName, ClassSingleLoadStack[i]->WealthEntry->WealthClass);}else {// 生成相应类型的对象并且传递对象到请求者if (ClassSingleLoadStack[i]->WealthEntry->WealthType == EWealthType::Object) {UObject* InstObject = NewObject<UObject>(this, ClassSingleLoadStack[i]->WealthEntry->WealthClass);InstObject->AddToRoot();BackObject(ModuleIndex, ClassSingleLoadStack[i]->ObjectName, ClassSingleLoadStack[i]->FunName, ClassSingleLoadStack[i]->WealthEntry->WealthName, InstObject);}else if (ClassSingleLoadStack[i]->WealthEntry->WealthType == EWealthType::Actor) {AActor* InstActor = GetDDWorld()->SpawnActor<AActor>(ClassSingleLoadStack[i]->WealthEntry->WealthClass, ClassSingleLoadStack[i]->SpawnTransform);BackActor(ModuleIndex, ClassSingleLoadStack[i]->ObjectName, ClassSingleLoadStack[i]->FunName, ClassSingleLoadStack[i]->WealthEntry->WealthName, InstActor);}else if (ClassSingleLoadStack[i]->WealthEntry->WealthType == EWealthType::Widget) {UUserWidget* InstWidget = CreateWidget<UUserWidget>(GetDDWorld(), ClassSingleLoadStack[i]->WealthEntry->WealthClass);// 避免回收GCWidgetGroup.Push(InstWidget);BackWidget(ModuleIndex, ClassSingleLoadStack[i]->ObjectName, ClassSingleLoadStack[i]->FunName, ClassSingleLoadStack[i]->WealthEntry->WealthName, InstWidget);}}CompleteStack.Push(ClassSingleLoadStack[i]);}}for (int i = 0; i < CompleteStack.Num(); ++i) {ClassSingleLoadStack.Remove(CompleteStack[i]);delete CompleteStack[i];}
}void UDDWealth::BuildSingleClassWealth(EWealthType WealthType, FName WealthName, FName ObjectName, FName FunName, FTransform SpawnTransform)
{// 获取对应的资源结构体FClassWealthEntry* WealthEntry = GetClassSingleEntry(WealthName);// 如果为空if (!WealthEntry) {DDH::Debug() << ObjectName << " Get Null Wealth : " << WealthName << DDH::Endl();return;}// 如果资源不可用if (!WealthEntry->WealthPtr.ToSoftObjectPath().IsValid()) {DDH::Debug() << ObjectName << " Get UnValid Wealth : " << WealthName << DDH::Endl();return;}// 资源类型是否匹配if (WealthEntry->WealthType != WealthType) {DDH::Debug() << ObjectName << " Get Error Type : " << DDH::Endl();return;}// 如果资源已经加载if (WealthEntry->WealthClass) {// 根据类型来执行不同生成逻辑并且传递对象到请求者if (WealthType == EWealthType::Object) {UObject* InstObject = NewObject<UObject>(this, WealthEntry->WealthClass);InstObject->AddToRoot();// 传递对象到请求者BackObject(ModuleIndex, ObjectName, FunName, WealthName, InstObject);}else if (WealthType == EWealthType::Actor) {AActor* InstActor = GetDDWorld()->SpawnActor<AActor>(WealthEntry->WealthClass, SpawnTransform);BackActor(ModuleIndex, ObjectName, FunName, WealthName, InstActor);}else if (WealthType == EWealthType::Widget) {UUserWidget* InstWidget = CreateWidget<UUserWidget>(GetDDWorld(), WealthEntry->WealthClass);// 避免回收GCWidgetGroup.Push(InstWidget);BackWidget(ModuleIndex, ObjectName, FunName, WealthName, InstWidget);}}else {// 异步加载,获取加载句柄TSharedPtr<FStreamableHandle> WealthHandle = WealthLoader.RequestAsyncLoad(WealthEntry->WealthPtr.ToSoftObjectPath());// 创建新加载节点ClassSingleLoadStack.Push(new ClassSingleLoadNode(WealthHandle, WealthEntry, ObjectName, FunName, SpawnTransform));}
}

补全 DDWealth – DDModule – DDOO – 对象 的调用链。

DDModule.h

public:	// 创建一个对象实例void BuildSingleClassWealth(EWealthType WealthType, FName WealthName, FName ObjectName, FName FunName, FTransform SpawnTransform);

DDModule.cpp

void UDDModule::BuildSingleClassWealth(EWealthType WealthType, FName WealthName, FName ObjectName, FName FunName, FTransform SpawnTransform)
{Wealth->BuildSingleClassWealth(WealthType, WealthName, ObjectName,  FunName, SpawnTransform);
}

DDOO 有些不一样,它需要额外判断是否需要传入生成位置,这是专门为 Actor 准备的。

DDOO.h

protected:// 创建一个对象实例// 给 Object 和 Widget 用的void BuildSingleClassWealth(EWealthType WealthType, FName WealthName, FName FunName);// 给 Actor 用的void BuildSingleClassWealth(EWealthType WealthType, FName WealthName, FName FunName, FTransform SpawnTransform);

DDOO.cpp

void IDDOO::BuildSingleClassWealth(EWealthType WealthType, FName WealthName, FName FunName)
{IModule->BuildSingleClassWealth(WealthType, WealthName, GetObjectName(), FunName, FTransform::Identity);
}void IDDOO::BuildSingleClassWealth(EWealthType WealthType, FName WealthName, FName FunName, FTransform SpawnTransform)
{IModule->BuildSingleClassWealth(WealthType, WealthName, GetObjectName(), FunName, SpawnTransform);
}

测试加载并创建单个 UClass 资源对象

我们打算只测试创建一个 Actor 资源对象,并且让它一直旋转。

WealthCallObject.h

public:virtual void DDTick(float DeltaSeconds) override;// 回调方法UFUNCTION()void BuildActor(FName BackName, AActor* BackActor);public:// 保存返回的 ActorAActor* SingleActor;

WealthCallObject.cpp

void UWealthCallObject::DDLoading()
{Super::DDLoading();IsAllowTickEvent = true;	// 实际上开启帧函数的bool值这个最好放在 DDInit()// ... 省略// 测试完毕后记得注释掉BuildSingleClassWealth(EWealthType::Actor, "ViewActor1", "BuildActor", ViewTrans);	
}void UWealthCallObject::DDTick(float DeltaSeconds)
{Super::DDTick(DeltaSeconds);if (SingleActor) {SingleActor->AddActorWorldRotation(FRotator(1.f, 0.f, 0.f));}
}void UWealthCallObject::BuildActor(FName BackName, AActor* BackActor)
{DDH::Debug() << BackName << DDH::Endl();SingleActor = BackActor;
}

编译后运行游戏,可以看见左上角输出了 ViewActor1,场景中生成了 ViewActor1,并且它一直在旋转。说明加载并创建 UClass 对象的逻辑写好了。

在这里插入图片描述
顺便打开 PlayerData 将 AutoActorData 下的两个对象去掉,免得在场景里占位置。

48. 创建同类资源对象

接下来实现创建多个同种类名(WealthKind)的资源对象实例后返回给申请者。

DDWealth.h 里的反射回调函数的声明宏,调整一下原本第一个参数的命名,加一个 Single,避免与最后一个参数重名。并且 .cpp 里对应的调用语句也要跟着修改。

DDWealth.h

public:// 创建同资源种类名的对象实例,同种类名下的每个资源链接创建一个对象实例void BuildKindClassWealth(EWealthType WealthType, FName WealthKind, FName ObjectName, FName FunName, TArray<FTransform> SpawnTransforms);protected:// 给之前的生成单个对象的反射回调函数,函数名后添加 “Single”DDOBJFUNC_TWO(BackObjectSingle, FName, BackName, UObject*, BackObject);// 添加同种类 Object 的反射回调函数DDOBJFUNC_TWO(BackObjectKind, TArray<FName>, BackNames, TArray<UObject*>, BackObjects);DDOBJFUNC_TWO(BackActorSingle, FName, BackName, AActor*, BackActor);// 添加同种类 Actor 的反射回调函数DDOBJFUNC_TWO(BackActorKind, TArray<FName>, BackNames, TArray<AActor*>, BackActors);DDOBJFUNC_TWO(BackWidgetSingle, FName, BackName, UUserWidget*, BackWidget);// 添加同种类 Widget 的反射回调函数DDOBJFUNC_TWO(BackWidgetKind, TArray<FName>, BackNames, TArray<UUserWidget*>, BackWidgets);

DDWealth.cpp

struct ClassKindLoadNode
{TSharedPtr<FStreamableHandle> WealthHandle;TArray<FClassWealthEntry*> UnLoadWealthEntry;TArray<FClassWealthEntry*> LoadWealthEntry;FName ObjectName;FName FunName;// 多个生成位置TArray<FTransform> SpawnTransforms;// 是否只加载 Classbool IsLoadClass;// 保存生成的对象与名字TArray<FName> NameGroup;TArray<UObject*> ObjectGroup;TArray<AActor*> ActorGroup;TArray<UUserWidget*> WidgetGroup;ClassKindLoadNode(TSharedPtr<FStreamableHandle> InWealthHandle, TArray<FClassWealthEntry*> InUnLoadWealthEntry, TArray<FClassWealthEntry*>& InLoadWealthEntry, FName InObjectName, FName InFunName){WealthHandle = InWealthHandle;UnLoadWealthEntry = InUnLoadWealthEntry;LoadWealthEntry = InLoadWealthEntry;ObjectName = InObjectName;FunName = InFunName;IsLoadClass = true;		// 补充}// 创建 UClass 对象所使用的构造函数ClassKindLoadNode(TSharedPtr<FStreamableHandle> InWealthHandle, TArray<FClassWealthEntry*> InUnLoadWealthEntry, TArray<FClassWealthEntry*>& InLoadWealthEntry, FName InObjectName, FName InFunName, TArray<FTransform> InSpawnTransforms){WealthHandle = InWealthHandle;UnLoadWealthEntry = InUnLoadWealthEntry;LoadWealthEntry = InLoadWealthEntry;ObjectName = InObjectName;FunName = InFunName;SpawnTransforms = InSpawnTransforms;IsLoadClass = false;	}
};void UDDWealth::DealClassSingleLoadStack()
{// ... 省略else {if (ClassSingleLoadStack[i]->WealthEntry->WealthType == EWealthType::Object) {UObject* InstObject = NewObject<UObject>(this, ClassSingleLoadStack[i]->WealthEntry->WealthClass);InstObject->AddToRoot();// 更改BackObjectSingle(ModuleIndex, ClassSingleLoadStack[i]->ObjectName, ClassSingleLoadStack[i]->FunName, ClassSingleLoadStack[i]->WealthEntry->WealthName, InstObject);}else if (ClassSingleLoadStack[i]->WealthEntry->WealthType == EWealthType::Actor) {AActor* InstActor = GetDDWorld()->SpawnActor<AActor>(ClassSingleLoadStack[i]->WealthEntry->WealthClass, ClassSingleLoadStack[i]->SpawnTransform);// 更改BackActorSingle(ModuleIndex, ClassSingleLoadStack[i]->ObjectName, ClassSingleLoadStack[i]->FunName, ClassSingleLoadStack[i]->WealthEntry->WealthName, InstActor);}else if (ClassSingleLoadStack[i]->WealthEntry->WealthType == EWealthType::Widget) {UUserWidget* InstWidget = CreateWidget<UUserWidget>(GetDDWorld(), ClassSingleLoadStack[i]->WealthEntry->WealthClass);GCWidgetGroup.Push(InstWidget);// 更改BackWidgetSingle(ModuleIndex, ClassSingleLoadStack[i]->ObjectName, ClassSingleLoadStack[i]->FunName, ClassSingleLoadStack[i]->WealthEntry->WealthName, InstWidget);}}CompleteStack.Push(ClassSingleLoadStack[i]);}}// ... 省略
}void UDDWealth::DealClassKindLoadStack()
{TArray<ClassKindLoadNode*> CompleteStack;for (int i = 0; i < ClassKindLoadStack.Num(); ++i) {// 补充判断条件,句柄可用才继续执行加载if (ClassKindLoadStack[i]->WealthHandle.IsValid() && ClassKindLoadStack[i]->WealthHandle->HasLoadCompleted() && ClassKindLoadStack[i]->UnLoadWealthEntry.Num() > 0) {// ... 省略}if (ClassKindLoadStack[i]->UnLoadWealthEntry.Num() == 0) {// 将原来的代码多套一层 if 判断,确定是否要生成对象// 加载 UClass 或者直接生成资源的情况来处理if(ClassKindLoadStack[i]->IsLoadClass) {TArray<FName> NameGroup;TArray<UClass*> WealthGroup;for (int j = 0; j < ClassKindLoadStack[i]->LoadWealthEntry.Num(); ++j) {NameGroup.Push(ClassKindLoadStack[i]->LoadWealthEntry[j]->WealthName);WealthGroup.Push(ClassKindLoadStack[i]->LoadWealthEntry[j]->WealthClass);}BackClassWealthKind(ModuleIndex, ClassKindLoadStack[i]->ObjectName, ClassKindLoadStack[i]->FunName, NameGroup, WealthGroup);CompleteStack.Push(ClassKindLoadStack[i]);}	else {	// 如果要生成对象// 从已加载的资源数组中取出第一个FClassWealthEntry* WealthEntry = ClassKindLoadStack[i]->LoadWealthEntry[0];// 移除出序列ClassKindLoadStack[i]->LoadWealthEntry.RemoveAt(0);// 根据资源类型生成对象if (WealthEntry->WealthType == EWealthType::Object) {UObject* InstObject = NewObject<UObject>(this, WealthEntry->WealthClass);InstObject->AddToRoot();// 添加找参数数组ClassKindLoadStack[i]->NameGroup.Push(WealthEntry->WealthName);ClassKindLoadStack[i]->ObjectGroup.Push(InstObject);// 判断是否生成了全部的对象if (ClassKindLoadStack[i]->LoadWealthEntry.Num() == 0) {// 给请求者传递生成的对象BackObjectKind(ModuleIndex, ClassKindLoadStack[i]->ObjectName, ClassKindLoadStack[i]->FunName, ClassKindLoadStack[i]->NameGroup, ClassKindLoadStack[i]->ObjectGroup);// 添加到完成序列CompleteStack.Push(ClassKindLoadStack[i]);}}else if (WealthEntry->WealthType == EWealthType::Actor) {// 获取生成位置FTransform SpawnTransform = ClassKindLoadStack[i]->SpawnTransforms.Num() == 1 ? ClassKindLoadStack[i]->SpawnTransforms[0] : ClassKindLoadStack[i]->SpawnTransforms[ClassKindLoadStack[i]->ActorGroup.Num()];// 生成对象AActor* InstActor = GetDDWorld()->SpawnActor<AActor>(WealthEntry->WealthClass, SpawnTransform);// 添加找参数数组ClassKindLoadStack[i]->NameGroup.Push(WealthEntry->WealthName);ClassKindLoadStack[i]->ActorGroup.Push(InstActor);// 判断是否生成了全部的对象if (ClassKindLoadStack[i]->LoadWealthEntry.Num() == 0) {// 给请求者传递生成的对象BackActorKind(ModuleIndex, ClassKindLoadStack[i]->ObjectName, ClassKindLoadStack[i]->FunName, ClassKindLoadStack[i]->NameGroup, ClassKindLoadStack[i]->ActorGroup);// 添加到完成序列CompleteStack.Push(ClassKindLoadStack[i]);}}else if (WealthEntry->WealthType == EWealthType::Widget) {UUserWidget* InstWidget = CreateWidget<UUserWidget>(GetDDWorld(), WealthEntry->WealthClass);// 避免回收GCWidgetGroup.Push(InstWidget);// 添加找参数数组ClassKindLoadStack[i]->NameGroup.Push(WealthEntry->WealthName);ClassKindLoadStack[i]->WidgetGroup.Push(InstWidget);// 判断是否生成了全部的对象if (ClassKindLoadStack[i]->LoadWealthEntry.Num() == 0) {// 给请求者传递生成的对象BackWidgetKind(ModuleIndex, ClassKindLoadStack[i]->ObjectName, ClassKindLoadStack[i]->FunName, ClassKindLoadStack[i]->NameGroup, ClassKindLoadStack[i]->WidgetGroup);// 添加到完成序列CompleteStack.Push(ClassKindLoadStack[i]);}}}	}}// ... 省略
}void UDDWealth::BuildSingleClassWealth(EWealthType WealthType, FName WealthName, FName ObjectName, FName FunName, FTransform SpawnTransform)
{// ... 省略if (WealthEntry->WealthClass) {if (WealthType == EWealthType::Object) {UObject* InstObject = NewObject<UObject>(this, WealthEntry->WealthClass);InstObject->AddToRoot();// 更改BackObjectSingle(ModuleIndex, ObjectName, FunName, WealthName, InstObject);}else if (WealthType == EWealthType::Actor) {AActor* InstActor = GetDDWorld()->SpawnActor<AActor>(WealthEntry->WealthClass, SpawnTransform);// 更改BackActorSingle(ModuleIndex, ObjectName, FunName, WealthName, InstActor);}else if (WealthType == EWealthType::Widget) {UUserWidget* InstWidget = CreateWidget<UUserWidget>(GetDDWorld(), WealthEntry->WealthClass);GCWidgetGroup.Push(InstWidget);// 更改BackWidgetSingle(ModuleIndex, ObjectName, FunName, WealthName, InstWidget);}}// ... 省略
}void UDDWealth::BuildKindClassWealth(EWealthType WealthType, FName WealthKind, FName ObjectName, FName FunName, TArray<FTransform> SpawnTransforms)
{TArray<FClassWealthEntry*> WealthEntryGroup = GetClassKindEntry(WealthKind);// 为 0 则说明不存在该资源种类if (WealthEntryGroup.Num() == 0) {DDH::Debug() << ObjectName << " Get Null WealthKind : " << WealthKind << DDH::Endl();return;}for (int i = 0; i < WealthEntryGroup.Num(); ++i) {// 资源可用性if (!WealthEntryGroup[i]->WealthPtr.ToSoftObjectPath().IsValid()) {DDH::Debug() << ObjectName << " Get Not Valid In Kind : " << WealthKind << " For Name : " << WealthEntryGroup[i]->WealthName << DDH::Endl();return;}// 如果资源类型不匹配if (WealthEntryGroup[i]->WealthType != WealthType) {DDH::Debug() << ObjectName << " Get Error Type In Kind : " << WealthKind << " For Name : " << WealthEntryGroup[i]->WealthName << DDH::Endl();return;}}// 对于 Actor,有多少个对象就有多少个 Transform;对于 Object 和 Widget 则只有一个 Transform// 判断 Transform 数组是否为 1 或者是否为 WealthEntryGroup 的数量if (WealthType == EWealthType::Actor && SpawnTransforms.Num() != 1 && SpawnTransforms.Num() != WealthEntryGroup.Num()) {DDH::Debug() << ObjectName << " Send Error Spawn Count : " << WealthKind << DDH::Endl();return;}// 未加载的资源链接TArray<FClassWealthEntry*> UnLoadWealthEntry;// 已加载的资源链接TArray<FClassWealthEntry*> LoadWealthEntry;// 资源分类for (int i = 0; i < WealthEntryGroup.Num(); ++i) {if (WealthEntryGroup[i]->WealthClass)LoadWealthEntry.Push(WealthEntryGroup[i]);elseUnLoadWealthEntry.Push(WealthEntryGroup[i]);}// 声明一个加载句柄TSharedPtr<FStreamableHandle> WealthHandle;// 如果有未加载的资源if (UnLoadWealthEntry.Num() > 0) {// 获取资源路径TArray<FSoftObjectPath> WealthPaths;for (int i = 0; i < UnLoadWealthEntry.Num(); ++i)WealthPaths.Push(UnLoadWealthEntry[i]->WealthPtr.ToSoftObjectPath());// 获取加载句柄WealthHandle = WealthLoader.RequestAsyncLoad(WealthPaths);}// 创建帧处理的节点ClassKindLoadStack.Push(new ClassKindLoadNode(WealthHandle, UnLoadWealthEntry, LoadWealthEntry, ObjectName, FunName, SpawnTransforms));
}

剩余部分(补全调用链与测试功能)留到下一节课。


文章转载自:
http://dinncocouture.wbqt.cn
http://dinncoquizmaster.wbqt.cn
http://dinncostaggart.wbqt.cn
http://dinncotrunk.wbqt.cn
http://dinncoempower.wbqt.cn
http://dinncograndsire.wbqt.cn
http://dinncoallopatrically.wbqt.cn
http://dinncolockpick.wbqt.cn
http://dinncofondness.wbqt.cn
http://dinncomulct.wbqt.cn
http://dinncotontine.wbqt.cn
http://dinncogaya.wbqt.cn
http://dinncoenterograph.wbqt.cn
http://dinncofrigate.wbqt.cn
http://dinncothessalonica.wbqt.cn
http://dinncochemic.wbqt.cn
http://dinncoarchangel.wbqt.cn
http://dinncosouthernization.wbqt.cn
http://dinncomisguide.wbqt.cn
http://dinncodiffusor.wbqt.cn
http://dinncoomphale.wbqt.cn
http://dinncoalpinism.wbqt.cn
http://dinncohomeostasis.wbqt.cn
http://dinncodemilitarization.wbqt.cn
http://dinncosouthing.wbqt.cn
http://dinncostrychnine.wbqt.cn
http://dinncolaystall.wbqt.cn
http://dinncoturnery.wbqt.cn
http://dinncolingayat.wbqt.cn
http://dinncoevacuator.wbqt.cn
http://dinncotremblingly.wbqt.cn
http://dinncodiesis.wbqt.cn
http://dinncodiplotene.wbqt.cn
http://dinncogametangium.wbqt.cn
http://dinncotropotaxis.wbqt.cn
http://dinncomicromail.wbqt.cn
http://dinncozalophus.wbqt.cn
http://dinncolithographer.wbqt.cn
http://dinncobluepoint.wbqt.cn
http://dinncouintahite.wbqt.cn
http://dinncoskete.wbqt.cn
http://dinncocaninity.wbqt.cn
http://dinncoparipinnate.wbqt.cn
http://dinncoscarves.wbqt.cn
http://dinncoplaybroker.wbqt.cn
http://dinncokleig.wbqt.cn
http://dinncodriftlessness.wbqt.cn
http://dinncolysolecithin.wbqt.cn
http://dinncoeva.wbqt.cn
http://dinncoportend.wbqt.cn
http://dinncopulj.wbqt.cn
http://dinncoebb.wbqt.cn
http://dinncoiridescent.wbqt.cn
http://dinncoindentureship.wbqt.cn
http://dinncomultifunctional.wbqt.cn
http://dinncovolar.wbqt.cn
http://dinncointimation.wbqt.cn
http://dinncowoken.wbqt.cn
http://dinncospatterware.wbqt.cn
http://dinncocheckage.wbqt.cn
http://dinncofacto.wbqt.cn
http://dinncorisk.wbqt.cn
http://dinncoalterability.wbqt.cn
http://dinncolegislatorship.wbqt.cn
http://dinncoodm.wbqt.cn
http://dinncoaquamarine.wbqt.cn
http://dinncoremover.wbqt.cn
http://dinncoliquorice.wbqt.cn
http://dinncotheopathy.wbqt.cn
http://dinncohibernation.wbqt.cn
http://dinncodulcin.wbqt.cn
http://dinncogreed.wbqt.cn
http://dinncosemidwarf.wbqt.cn
http://dinncoquinquepartite.wbqt.cn
http://dinncointriguant.wbqt.cn
http://dinncosouthwestward.wbqt.cn
http://dinncobefittingly.wbqt.cn
http://dinncoabstrusely.wbqt.cn
http://dinncoanorthic.wbqt.cn
http://dinncoemotionality.wbqt.cn
http://dinncomorel.wbqt.cn
http://dinncoretinite.wbqt.cn
http://dinncoliquorous.wbqt.cn
http://dinncofraudulency.wbqt.cn
http://dinncomisjudgment.wbqt.cn
http://dinncosuperman.wbqt.cn
http://dinncovitoria.wbqt.cn
http://dinncodundee.wbqt.cn
http://dinncoagrologist.wbqt.cn
http://dinncogiantlike.wbqt.cn
http://dinncopeshitta.wbqt.cn
http://dinncobenignity.wbqt.cn
http://dinncoament.wbqt.cn
http://dinncoschizogenic.wbqt.cn
http://dinncononlicet.wbqt.cn
http://dinncoweatherworn.wbqt.cn
http://dinncomandamus.wbqt.cn
http://dinncoyaleman.wbqt.cn
http://dinncopillaret.wbqt.cn
http://dinnconettlesome.wbqt.cn
http://www.dinnco.com/news/108708.html

相关文章:

  • 给网站做cdn推广软文
  • o2o的代表平台有哪些湖南网站seo营销
  • 石家庄谁会搭建网站读书网站排名
  • 网站推广意识薄弱短视频seo系统
  • 怎么做英文垃圾网站好f123网站
  • 网站建设广东常州网络推广平台
  • 本地网站建设网站建设与网页设计制作
  • WordPress独立留言板页面中国网民博客 seo
  • 私人网站如何做竞价核心关键词如何优化
  • 简单的网站设计怎么做重庆网站建设外包
  • 珠海网站策划seo相关ppt
  • 淘宝上做网站排名免费的郑州网络推广服务
  • 高端大气装饰公司网站源码 百度网盘怎么搭建属于自己的网站
  • 手机网站无响应免费涨1000粉丝网站
  • 门户类网站建设大约多少钱百度app客服电话
  • 北京的网站建设搜索引擎营销分析
  • java script 做网站买卖链接网
  • 哪个网站可以做空比特币如何优化网站快速排名
  • 网站单页支付宝支付怎么做的廊坊百度推广电话
  • 一个人怎么做网站想做个网络推广
  • wordpress边栏浮动新河seo怎么做整站排名
  • 我国政府门户网站的建设营销推广方案包括哪些内容
  • 中山做百度网站的公司名称seo实战密码第三版
  • 虚拟主机怎么弄网站网站做优化好还是推广好
  • 济南网站制作工作室关键词林俊杰的寓意
  • 低学历吃香的十大职业武汉seo报价
  • 北京建设工程交易服务中心网站seo推广公司哪家好
  • 网站建设阶段的推广企业培训机构排名
  • 哪些公司的网站做的很好网络推广产品公司
  • 方法网站目录关键词搜索量查询