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

43. 单个加载 UObject 功能

获取资源 URL 链接

继续来补充根据资源类型生成资源的逻辑,在 DDWealth 里添加获取 URL 的方法。

DDWealth.h

public:

	// 外部方法单纯获取资源链接
	// 返回单个 URL
	FWealthURL* GainWealthURL(FName WealthName);
	// 返回一个种类的资源的 URL
	void GainWealthURL(FName WealthKind, TArray<FWealthURL*>& OutURL);

DDWealth.cpp

FWealthURL* UDDWealth::GainWealthURL(FName WealthName)
{
   
	// 从 DataAsset 里遍历获取对应名字的资源的 URL
	for (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, TArray<FWealthURL*>& OutURL)
{
   
	// 从 DataAsset 里遍历获取对应种类名字的全部资源的 URL
	for (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, TArray<FWealthURL*>& OutURL);

DDModule.cpp

FWealthURL* UDDModule::GainWealthURL(FName WealthName)
{
   
	return Wealth->GainWealthURL(WealthName);
}

void UDDModule::GainWealthURL(FName WealthKind, TArray<FWealthURL*>& OutURL)
{
   
	Wealth->GainWealthURL(WealthKind, OutURL);
}

DDOO.h

protected:

	// 外部方法单纯获取资源链接
	FWealthURL* GainWealthURL(FName WealthName);
	
	void GainWealthURL(FName WealthKind, TArray<FWealthURL*>& OutURL);

DDOO.cpp

FWealthURL* IDDOO::GainWealthURL(FName WealthName)
{
   
	return IModule->GainWealthURL(WealthName);
}

void IDDOO::GainWealthURL(FName WealthKind, TArray<FWealthURL*>& 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);
	
	TArray<FObjectWealthEntry*> GetObjectKindEntry(FName WealthKind);

	// 处理加载单个 Object 节点的方法,放在 Tick() 里
	void DealObjectSingleLoadStack();

protected:

	// 加载器,用于异步加载
	FStreamableManager WealthLoader;


	// 加载节点队列
	TArray<ObjectSingleLoadNode*> ObjectSingleLoadStack;

protected:

	// 加载 UObject 反射回调函数,方便返回已经生成的资源
	DDOBJFUNC_TWO(BackObjectWealth, FName, BackName, UObject*, BackWealth);

	DDOBJFUNC_TWO(BackObjectWealthKind, TArray<FName>, BackNames, TArray<UObject*>, BackWealths);
};

DDWealth.cpp

struct ObjectSingleLoadNode
{
   
	// 加载句柄
	TSharedPtr<FStreamableHandle> WealthHandle;
	// 资源结构体
	FObjectWealthEntry* WealthEntry;
	// 请求对象名
	FName ObjectName;
	// 回调方法名
	FName FunName;
	// 构造函数
	ObjectSingleLoadNode(TSharedPtr<FStreamableHandle> 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 {
   <
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值