做公益活动的网站,广州市网站建设价格,升级wordpress,股票可以做网站推广吗UE4运用C和框架开发坦克大战教程笔记#xff08;十四#xff09;#xff08;第43~45集#xff09; 43. 单个加载 UObject 功能获取资源 URL 链接实现异步加载单个 UObject 类型资源 44. 批量加载 UObject 功能测试加载单个 UObject 资源批量加载多个同类的 UObject 资源 45… UE4运用C和框架开发坦克大战教程笔记十四第43~45集 43. 单个加载 UObject 功能获取资源 URL 链接实现异步加载单个 UObject 类型资源 44. 批量加载 UObject 功能测试加载单个 UObject 资源批量加载多个同类的 UObject 资源 45. 单个加载 UClass 功能测试加载多个 UObject 资源异步加载单个 UClass 类型的资源 43. 单个加载 UObject 功能
获取资源 URL 链接
继续来补充根据资源类型生成资源的逻辑在 DDWealth 里添加获取 URL 的方法。
DDWealth.h
public:// 外部方法单纯获取资源链接// 返回单个 URLFWealthURL* GainWealthURL(FName WealthName);// 返回一个种类的资源的 URLvoid GainWealthURL(FName WealthKind, TArrayFWealthURL* OutURL);DDWealth.cpp
FWealthURL* UDDWealth::GainWealthURL(FName WealthName)
{// 从 DataAsset 里遍历获取对应名字的资源的 URLfor (int i 0; i WealthData.Num(); i) {for (int j 0; j WealthData[i]-WealthURL.Num(); j) {if (WealthData[i]-WealthURL[j].WealthName.IsEqual(WealthName))return WealthData[i]-WealthURL[j];}}return NULL;
}void UDDWealth::GainWealthURL(FName WealthKind, TArrayFWealthURL* OutURL)
{// 从 DataAsset 里遍历获取对应种类名字的全部资源的 URLfor (int i 0; i WealthData.Num(); i) {for (int j 0; j WealthData[i]-WealthURL.Num(); j) {if (WealthData[i]-WealthURL[j].WealthKind.IsEqual(WealthKind))OutURL.Push(WealthData[i]-WealthURL[j]);}}
}建立 DDWealth – DDModule – DDOO – 对象 的调用链。
DDModule.h
public:// 外部方法单纯获取资源链接FWealthURL* GainWealthURL(FName WealthName);void GainWealthURL(FName WealthKind, TArrayFWealthURL* OutURL);DDModule.cpp
FWealthURL* UDDModule::GainWealthURL(FName WealthName)
{return Wealth-GainWealthURL(WealthName);
}void UDDModule::GainWealthURL(FName WealthKind, TArrayFWealthURL* OutURL)
{Wealth-GainWealthURL(WealthKind, OutURL);
}DDOO.h
protected:// 外部方法单纯获取资源链接FWealthURL* GainWealthURL(FName WealthName);void GainWealthURL(FName WealthKind, TArrayFWealthURL* OutURL);DDOO.cpp
FWealthURL* IDDOO::GainWealthURL(FName WealthName)
{return IModule-GainWealthURL(WealthName);
}void IDDOO::GainWealthURL(FName WealthKind, TArrayFWealthURL* OutURL)
{IModule-GainWealthURL(WealthKind, OutURL);
}如果编译通过则说明写好了现在所有的对象都可以通过这两个方法获取目标资源的 URL。刚刚写的这些代码结构也比较简单此处就跳过验证环节。
实现异步加载单个 UObject 类型资源
异步加载需要用到引擎提供的 StreamableManager所以我们声明一个存放 Object 资源数据的结构体里面还包含着 FStreamableHandle 句柄以便参与异步加载。
在 DDWealth 内的逻辑如下结构体作为加载节点并且声明一个它的数组作为加载节点队列。Tick() 内检测到队列内的节点是否已经加载完毕是则将其从队列里删除。对象只需要调用 LoadObjectWealth() 就可以开始异步加载并且生成目标 Object 资源的加载节点后将其放入队列。
DDWealth.h
#include Engine/StreamableManager.h // 引入头文件
#include DDWealth.generated.h// 加载单个 Object 资源的节点
struct ObjectSingleLoadNode;UCLASS()
class DATADRIVEN_API UDDWealth : public UObject, public IDDMM
{GENERATED_BODY()public:// 加载 Object 类型资源接口void LoadObjectWealth(FName WealthName, FName ObjectName, FName FunName);// 加载 Object 类型的同种类的所有资源void LoadObjectWealthKind(FName WealthKind, FName ObjectName, FName FunName);protected:// 获取 Object 资源结构体FObjectWealthEntry* GetObjectSingleEntry(FName WealthName);TArrayFObjectWealthEntry* GetObjectKindEntry(FName WealthKind);// 处理加载单个 Object 节点的方法放在 Tick() 里void DealObjectSingleLoadStack();protected:// 加载器用于异步加载FStreamableManager WealthLoader;// 加载节点队列TArrayObjectSingleLoadNode* ObjectSingleLoadStack;protected:// 加载 UObject 反射回调函数方便返回已经生成的资源DDOBJFUNC_TWO(BackObjectWealth, FName, BackName, UObject*, BackWealth);DDOBJFUNC_TWO(BackObjectWealthKind, TArrayFName, BackNames, TArrayUObject*, BackWealths);
};DDWealth.cpp
struct ObjectSingleLoadNode
{// 加载句柄TSharedPtrFStreamableHandle WealthHandle;// 资源结构体FObjectWealthEntry* WealthEntry;// 请求对象名FName ObjectName;// 回调方法名FName FunName;// 构造函数ObjectSingleLoadNode(TSharedPtrFStreamableHandle InWealthHandle, FObjectWealthEntry* InWealthEntry, FName InObjectName, FName InFunName){WealthHandle InWealthHandle;WealthEntry InWealthEntry;ObjectName InObjectName;FunName InFunName;}
};void UDDWealth::WealthTick(float DeltaSeconds)
{// 在 Tick() 里检查队列中的加载节点是否完成DealObjectSingleLoadStack();
}void UDDWealth::LoadObjectWealth(FName WealthName, FName ObjectName, FName FunName)
{// 获取资源结构体FObjectWealthEntry* WealthEntry GetObjectSingleEntry(WealthName);// 如果没有这个名字对应的资源结构体if (!WealthEntry) {DDH::Debug() ObjectName Get Null Wealth : WealthName DDH::Endl();return;}// 如果资源不可用if (!WealthEntry-WealthPath.IsValid()) {DDH::Debug() ObjectName Get UnValid Wealth : WealthName DDH::Endl();return;}// 如果资源已经加载if (WealthEntry-WealthObject) {// 直接返回已经存在的资源给对象整个 BackObjectWealth 方法已经由反射系统的宏生成BackObjectWealth(ModuleIndex, ObjectName, FunName, WealthName, WealthEntry-WealthObject);}else {// 进行异步加载TSharedPtrFStreamableHandle WealthHandle WealthLoader.RequestAsyncLoad(WealthEntry-WealthPath);// 添加新节点到加载序列ObjectSingleLoadStack.Push(new ObjectSingleLoadNode(WealthHandle, WealthEntry, ObjectName, FunName));}
}// 批量加载同种类 UObject 暂时先不写留到下一节课
void UDDWealth::LoadObjectWealthKind(FName WealthKind, FName ObjectName, FName FunName)
{
}FObjectWealthEntry* UDDWealth::GetObjectSingleEntry(FName WealthName)
{for (int i 0; i WealthData.Num(); i) {for (int j 0; j WealthData[i]-ObjectWealthData.Num(); j) {if (WealthData[i]-ObjectWealthData[j].WealthName.IsEqual(WealthName))return (WealthData[i]-ObjectWealthData[j]);}}return NULL;
}TArrayFObjectWealthEntry* UDDWealth::GetObjectKindEntry(FName WealthKind)
{TArrayFObjectWealthEntry* WealthGroup;for (int i 0; i WealthData.Num(); i) {for (int j 0; j WealthData[i]-ObjectWealthData.Num(); j) {if (WealthData[i]-ObjectWealthData[j].WealthKind.IsEqual(WealthKind))WealthGroup.Push((WealthData[i]-ObjectWealthData[j]));}}return WealthGroup;
}void UDDWealth::DealObjectSingleLoadStack()
{// 定义加载完成的序列TArrayObjectSingleLoadNode* CompleteStack;for (int i 0; i ObjectSingleLoadStack.Num(); i) {// 判断是否已经加载完成if (ObjectSingleLoadStack[i]-WealthHandle-HasLoadCompleted()) {// 设置对应资源赋值给 WealthObjectObjectSingleLoadStack[i]-WealthEntry-WealthObject ObjectSingleLoadStack[i]-WealthEntry-WealthPath.ResolveObject();// 返回资源给对象BackObjectWealth(ModuleIndex, ObjectSingleLoadStack[i]-ObjectName, ObjectSingleLoadStack[i]-FunName, ObjectSingleLoadStack[i]-WealthEntry-WealthName, ObjectSingleLoadStack[i]-WealthEntry-WealthObject);// 添加已经加载完成的节点到临时序列CompleteStack.Push(ObjectSingleLoadStack[i]);}}// 销毁已经完成的节点for (int i 0; i CompleteStack.Num(); i) {// 移除出节点序列ObjectSingleLoadStack.Remove(CompleteStack[i]);// 释放内存delete CompleteStack[i];}
}剩余部分我们留到下一节课来实现。
44. 批量加载 UObject 功能
测试加载单个 UObject 资源
依旧是建立 DDWealth – DDModule – DDOO – 对象 的调用链。
虽然我们还没写批量加载同种类 UObject 资源的逻辑但是也可以顺便补充上这个调用链。
DDModule.h
public:// 加载 Object 类型资源接口void LoadObjectWealth(FName WealthName, FName ObjectName, FName FunName);void LoadObjectWealthKind(FName WealthKind, FName ObjectName, FName FunName);DDModule.cpp
void UDDModule::LoadObjectWealth(FName WealthName, FName ObjectName, FName FunName)
{Wealth-LoadObjectWealth(WealthName, ObjectName, FunName);
}void UDDModule::LoadObjectWealthKind(FName WealthKind, FName ObjectName, FName FunName)
{Wealth-LoadObjectWealthKind(WealthKind, ObjectName, FunName);
}DDOO 不需要传 ObjectName因为它本身保存着这个变量。
DDOO.h
protected:// 加载 Object 类型资源接口void LoadObjectWealth(FName WealthName, FName FunName);void LoadObjectWealthKind(FName WealthKind, FName FunName);DDOO.cpp
void IDDOO::LoadObjectWealth(FName WealthName, FName FunName)
{IModule-LoadObjectWealth(WealthName, GetObjectName(), FunName);
}void IDDOO::LoadObjectWealthKind(FName WealthKind, FName FunName)
{IModule-LoadObjectWealthKind(WealthKind, GetObjectName(), FunName);
}在项目的 .Bulid.cs 文件里添加对 UMG 的依赖。因为我们打算在 Widget 里放一个 Image 控件来让其显示加载的图片资源作为功能的验证过程。
RaceCarFrame.Build.cs
PublicDependencyModuleNames.AddRange(new string[] { Core, CoreUObject, Engine, InputCore, PhysXVehicles, HeadMountedDisplay, DataDriven, UMG }); // 添加依赖打开项目准备测试上面写的异步加载单个 UObject 功能。我们打算异步加载一张图片资源并将其应用到一个 Image 控件上。
创建一个以 DDUserWidget 为基类的 C 类目标模组为项目命名为 LoadWealthWidget。创建完毕后进行代码编译。
在 Blueprint 文件夹下基于 LoadWealthWidget 创建一个蓝图命名为 LoadWealthWidget_BP。
把 HUDData 里之前配置的目标 Widget 换成 LoadWealthWidget_BPObject Name 改成 LoadWealthWidget。
将 LoadWealthWidget_BP 修改成如下图 随后在 LoadWealthWidget 里添加加载 UObject 资源的逻辑并且将加载到的图片资源放进 Image 里。
LoadWealthWidget.h
class UImage;UCLASS()
class RACECARFRAME_API ULoadWealthWidget : public UDDUserWidget
{GENERATED_BODY()public:virtual void DDInit() override;virtual void DDLoading() override;UFUNCTION()void LoadSingleTexture(FName BackName, UObject* BackWealth);public:UPROPERTY(Meta (BindWidget))UImage* ViewImage;
};LoadWealthWidget.cpp
#include Components/Image.h // 引入头文件void ULoadWealthWidget::DDInit()
{Super::DDInit();AddToViewport(0);
}void ULoadWealthWidget::DDLoading()
{Super::DDLoading();// 调用加载资源的方法并且回调函数会被调用LoadObjectWealth(ViewImage1, LoadSingleTexture);
}void ULoadWealthWidget::LoadSingleTexture(FName BackName, UObject* BackWealth)
{ViewImage-SetBrushFromTexture(CastUTexture2D(BackWealth));
}编译后运行可看见左上角显示如下图 这是因为我们没有设置这个 “ViewImage1” 名称对应的目标图片资源。再次打开 HUDData设置如下 再次运行可见左上角的 Image 配置上了相应的图片。说明异步加载单个 UObject 资源的逻辑写好了。 批量加载多个同类的 UObject 资源
逻辑其实跟加载单个 UObject 资源差不多只是读取和加载利用 for 循环执行多次。
新声明一个 UObject 种类加载节点里面要声明存放多个资源结构体的数组。
DDWealth.h
struct ObjectKindLoadNode; // 添加结构体声明UCLASS()
class DATADRIVEN_API UDDWealth : public UObject, public IDDMM
{GENERATED_BODY()protected:// 处理批量加载 Object 节点的方法void DealObjectKindLoadStack();protected:TArrayObjectKindLoadNode* ObjectKindLoadStack;
};DDWealth.cpp struct ObjectKindLoadNode
{// 加载句柄TSharedPtrFStreamableHandle WealthHandle;// 没有加载的资源TArrayFObjectWealthEntry* UnLoadWealthEntry;// 已经加载的资源的数组TArrayFObjectWealthEntry* LoadWealthEntry;// 请求对象名FName ObjectName;// 回调方法名FName FunName;// 构造函数ObjectKindLoadNode(TSharedPtrFStreamableHandle InWealthHandle, TArrayFObjectWealthEntry* InUnLoadWealthEntry, TArrayFObjectWealthEntry* InLoadWealthEntry, FName InObjectName, FName InFunName){WealthHandle InWealthHandle;UnLoadWealthEntry InUnLoadWealthEntry;LoadWealthEntry InLoadWealthEntry;ObjectName InObjectName;FunName InFunName;}
};void UDDWealth::WealthTick(float DeltaSeconds)
{DealObjectKindLoadStack(); // 添加到 Tick()
}void UDDWealth::LoadObjectWealthKind(FName WealthKind, FName ObjectName, FName FunName)
{TArrayFObjectWealthEntry* WealthEntryGroup GetObjectKindEntry(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]-WealthPath.IsValid()) {DDH::Debug() ObjectName Get Not Valid in Kind : WealthKind For Name : WealthEntryGroup[i]-WealthName DDH::Endl();return;}}// 还没有加载的资源TArrayFObjectWealthEntry* UnLoadWealthEntry;// 已经加载的资源TArrayFObjectWealthEntry* LoadWealthEntry;// 资源加载与否归类for (int i 0; i WealthEntryGroup.Num(); i) {if (WealthEntryGroup[i]-WealthObject)LoadWealthEntry.Push(WealthEntryGroup[i]);elseUnLoadWealthEntry.Push(WealthEntryGroup[i]);}// 如果未加载的资源为 0if (UnLoadWealthEntry.Num() 0) {// 直接获取所有资源给请求对象TArrayFName NameGroup;TArrayUObject* WealthGroup;for (int i 0; i LoadWealthEntry.Num(); i) {NameGroup.Push(LoadWealthEntry[i]-WealthName);WealthGroup.Push(LoadWealthEntry[i]-WealthObject);}BackObjectWealthKind(ModuleIndex, ObjectName, FunName, NameGroup, WealthGroup);}else {// 获取资源路径TArrayFSoftObjectPath WealthPaths;for (int i 0; i UnLoadWealthEntry.Num(); i)WealthPaths.Push(UnLoadWealthEntry[i]-WealthPath);// 进行异步加载获取句柄TSharedPtrFStreamableHandle WealthHandle WealthLoader.RequestAsyncLoad(WealthPaths);// 生成加载节点ObjectKindLoadStack.Push(new ObjectKindLoadNode(WealthHandle, UnLoadWealthEntry, LoadWealthEntry, ObjectName, FunName));}
}void UDDWealth::DealObjectKindLoadStack()
{// 定义加载完成的序列TArrayObjectKindLoadNode* CompleteStack;for (int i 0; i ObjectKindLoadStack.Num(); i) {// 判断是否已经加载完成if (ObjectKindLoadStack[i]-WealthHandle-HasLoadCompleted()) {// 返回资源参数TArrayFName NameGroup;TArrayUObject* WealthGroup;// 填充已加载资源for (int j 0; j ObjectKindLoadStack[i]-LoadWealthEntry.Num(); j) {NameGroup.Push(ObjectKindLoadStack[i]-LoadWealthEntry[j]-WealthName);WealthGroup.Push(ObjectKindLoadStack[i]-LoadWealthEntry[j]-WealthObject);}// 遍历设置所有未加载资源结构体为已加载状态for (int j 0; j ObjectKindLoadStack[i]-UnLoadWealthEntry.Num(); j) {ObjectKindLoadStack[i]-UnLoadWealthEntry[j]-WealthObject ObjectKindLoadStack[i]-UnLoadWealthEntry[j]-WealthPath.ResolveObject();// 填充已加载资源NameGroup.Push(ObjectKindLoadStack[i]-UnLoadWealthEntry[j]-WealthName);WealthGroup.Push(ObjectKindLoadStack[i]-UnLoadWealthEntry[j]-WealthObject);}// 返回数据给请求对象BackObjectWealthKind(ModuleIndex, ObjectKindLoadStack[i]-ObjectName, ObjectKindLoadStack[i]-FunName, NameGroup, WealthGroup);// 添加节点到已完成序列CompleteStack.Push(ObjectKindLoadStack[i]);}}// 销毁已经完成的节点for (int i 0; i CompleteStack.Num(); i) {// 移除出节点序列ObjectKindLoadStack.Remove(CompleteStack[i]);// 释放内存delete CompleteStack[i];}
}验证部分我们留到下一节课。
45. 单个加载 UClass 功能
测试加载多个 UObject 资源
来到 LoadWealthWidget我们打算异步加载多张图片资源然后用之前的延时系统将图片每秒一张地换到 Image 控件上。
LoadWealthWidget.h
class UTexture2D;UCLASS()
class RACECARFRAME_API ULoadWealthWidget : public UDDUserWidget
{GENERATED_BODY()public:// 资源加载的回调函数UFUNCTION()void LoadKindTexture(TArrayFName BackNames, TArrayUObject* BackWealths);// 供延时系统使用的切换图片方法void ChangeImage();public:int32 ImageIndex;TArrayUTexture2D* TextureGroup;
};LoadWealthWidget.cpp
void ULoadWealthWidget::DDLoading()
{Super::DDLoading();//LoadObjectWealth(ViewImage1, LoadSingleTexture);// 测试完记得注释掉LoadObjectWealthKind(ViewImage, LoadKindTexture);
}void ULoadWealthWidget::LoadKindTexture(TArrayFName BackNames, TArrayUObject* BackWealths)
{for (int i 0; i BackWealths.Num(); i) {// 输出所有获取到的资源的名字DDH::Debug() BackNames[i] DDH::Endl();TextureGroup.Push(CastUTexture2D(BackWealths[i]));}ImageIndex 0;InvokeRepeat(ChangeImage, 1.f, 1.f, this, ULoadWealthWidget::ChangeImage);
}void ULoadWealthWidget::ChangeImage()
{ViewImage-SetBrushFromTexture(TextureGroup[ImageIndex]);ImageIndex ImageIndex 1 TextureGroup.Num() ? 0 : ImageIndex 1;
}编译后给 HUDData 中配置更多的图片并且将它们的 WealthKind 设置成同名老师配置了 11 张此处就截图 4 张以作示例 运行游戏可以看见左上角正在每秒一张地轮播刚刚配置的图片并且输出了 11 张图片的 Wealth Name。我们还可以发现它需要一定的时间一开始 Image 控件为空白来进行异步加载。 异步加载单个 UClass 类型的资源
加载 UClass 类型资源的逻辑跟加载 UObject 差不多区别在于
UObject 的资源链接用的是 FStringAssetReferenceUClass 的是 TSoftClassPtr它需要通过 ToSoftObjectPath() 转换成 FSoftObjectPath 才能参与到 UClass 类型的异步加载中。
DDWealth.h
// 加载单个 Class
struct ClassSingleLoadNode;UCLASS()
class DATADRIVEN_API UDDWealth : public UObject, public IDDMM
{GENERATED_BODY()public:// 加载 Class 类型资源接口void LoadClassWealth(FName WealthName, FName ObjectName, FName FunName);void LoadClassWealthKind(FName WealthKind, FName ObjectName, FName FunName);protected:// 获取 Class 资源结构体FClassWealthEntry* GetClassSingleEntry(FName WealthName);TArrayFClassWealthEntry* GetClassKindEntry(FName WealthKind);// 处理加载单个 Class 节点的方法void DealClassSingleLoadStack();protected:TArrayClassSingleLoadNode* ClassSingleLoadStack;protected:// 加载 UClass 反射回调函数DDOBJFUNC_TWO(BackClassWealth, FName, BackName, UClass*, BackWealth);DDOBJFUNC_TWO(BackClassWealthKind, TArrayFName, BackNames, TArrayUClass*, BackWealths);
};DDWealth.cpp
struct ClassSingleLoadNode
{// 加载句柄TSharedPtrFStreamableHandle WealthHandle;// 资源结构体FClassWealthEntry* WealthEntry;// 请求对象名FName ObjectName;// 回调方法名FName FunName;// 构造函数ClassSingleLoadNode(TSharedPtrFStreamableHandle InWealthHandle, FClassWealthEntry* InWealthEntry, FName InObjectName, FName InFunName){WealthHandle InWealthHandle;WealthEntry InWealthEntry;ObjectName InObjectName;FunName InFunName;}
};void UDDWealth::WealthTick(float DeltaSeconds)
{DealObjectSingleLoadStack();DealObjectKindLoadStack();DealClassSingleLoadStack(); // 每帧调用
}void UDDWealth::LoadClassWealth(FName WealthName, FName ObjectName, FName FunName)
{// 获取资源结构体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-WealthClass) {// 直接把资源返回给申请对象BackClassWealth(ModuleIndex, ObjectName, FunName, WealthName, WealthEntry-WealthClass);}else {// 进行异步加载TSharedPtrFStreamableHandle WealthHandle WealthLoader.RequestAsyncLoad(WealthEntry-WealthPtr.ToSoftObjectPath());// 添加节点ClassSingleLoadStack.Push(new ClassSingleLoadNode(WealthHandle, WealthEntry, ObjectName, FunName));}
}// 批量加载 UClass 资源的逻辑先不写
void UDDWealth::LoadClassWealthKind(FName WealthKind, FName ObjectName, FName FunName)
{
}FClassWealthEntry* UDDWealth::GetClassSingleEntry(FName WealthName)
{for (int i 0; i WealthData.Num(); i) {for (int j 0; j WealthData[i]-ClassWealthData.Num(); j) {if (WealthData[i]-ClassWealthData[j].WealthName.IsEqual(WealthName))return (WealthData[i]-ClassWealthData[j]);}}return NULL;
}TArrayFClassWealthEntry* UDDWealth::GetClassKindEntry(FName WealthKind)
{TArrayFClassWealthEntry* WealthGroup;for (int i 0; i WealthData.Num(); i) {for (int j 0; j WealthData[i]-ClassWealthData.Num(); j) {if (WealthData[i]-ClassWealthData[j].WealthKind.IsEqual(WealthKind))WealthGroup.Push((WealthData[i]-ClassWealthData[j]));}}return WealthGroup;
}void UDDWealth::DealClassSingleLoadStack()
{// 定义加载完成的序列TArrayClassSingleLoadNode* CompleteStack;for (int i 0; i ClassSingleLoadStack.Num(); i) {// 判断是否已经加载完成if (ClassSingleLoadStack[i]-WealthHandle-HasLoadCompleted()) {// 设置对应资源完成ClassSingleLoadStack[i]-WealthEntry-WealthClass CastUClass(ClassSingleLoadStack[i]-WealthEntry-WealthPtr.ToSoftObjectPath().ResolveObject());// 返回资源给对象BackClassWealth(ModuleIndex, ClassSingleLoadStack[i]-ObjectName, ClassSingleLoadStack[i]-FunName, ClassSingleLoadStack[i]-WealthEntry-WealthName, ClassSingleLoadStack[i]-WealthEntry-WealthClass);// 添加已经加载完成的节点到临时序列CompleteStack.Push(ClassSingleLoadStack[i]);}}// 销毁已经完成的节点for (int i 0; i CompleteStack.Num(); i) {// 移除出节点序列ClassSingleLoadStack.Remove(CompleteStack[i]);// 释放内存delete CompleteStack[i];}
}补充 DDWealth – DDModule – DDOO – 对象的调用链。
DDModule.h
public:// 加载 Class 类型资源接口void LoadClassWealth(FName WealthName, FName ObjectName, FName FunName);void LoadClassWealthKind(FName WealthKind, FName ObjectName, FName FunName);DDModule.cpp
void UDDModule::LoadClassWealth(FName WealthName, FName ObjectName, FName FunName)
{Wealth-LoadClassWealth(WealthName, ObjectName, FunName);
}void UDDModule::LoadClassWealthKind(FName WealthKind, FName ObjectName, FName FunName)
{Wealth-LoadClassWealthKind(WealthKind, ObjectName, FunName);
}DDOO.h
protected:// 加载 Class 类型资源接口void LoadClassWealth(FName WealthName, FName FunName);void LoadClassWealthKind(FName WealthKind, FName FunName);DDOO.cpp
void IDDOO::LoadClassWealth(FName WealthName, FName FunName)
{IModule-LoadClassWealth(WealthName, GetObjectName(), FunName);
}void IDDOO::LoadClassWealthKind(FName WealthKind, FName FunName)
{IModule-LoadClassWealthKind(WealthKind, GetObjectName(), FunName);
}接下来准备测试一下加载单个 UClass 类型资源的逻辑。我们打算让一个普通的 Actor 被加载到场景中。而调用异步加载 UClass 资源的方法就让 WealthCallObject它在 42 集开头通过配置在 PlayerData 里来生成来调用。
WealthCallObject.h
public:virtual void DDLoading() override;// 回调函数UFUNCTION()void LoadActorClass(FName BackName, UClass* BackWealth);public:// 生成位置UPROPERTY(EditAnywhere)FTransform ViewTrans;WealthCallObject.cpp
void UWealthCallObject::DDLoading()
{Super::DDLoading();// 测试完后记得注释掉LoadClassWealth(ViewActor1, LoadActorClass);
}void UWealthCallObject::LoadActorClass(FName BackName, UClass* BackWealth)
{GetDDWorld()-SpawnActorAActor(BackWealth, ViewTrans);
}编译后打开 WealthCallObject 蓝图设置位置如下 在 Blueprint 文件夹下创建一个基于 Actor 的蓝图命名为 ViewActor1给它添加一个网格体 打开 PlayerData配置如下 运行游戏可以看见目标地点生成了 ViewActor1。说明异步加载单个 UClass 类型资源的逻辑写好了。