ue4-异步加载资源
- 异步加载资源
ue中的异步加载分为两种模式,具体源码在 AsyncLoading.cpp 中
- 主线程分帧加载。
- 多线程加载。
可以通过接口判断当前的异步模式是那种模式。
1
const bool bIsMultithreaded = FAsyncLoadingThread::IsMultithreaded();
思路
- 一个FVCharPartInfo物件结构体,里面id和TAssetPtr
对mesh资源的的指针。 - 一个UItemInfoDatabase物件数据库,里面有一个物件列表TArray
- 一个全局单例类USolusDataSingleton,里面有个资源加载器struct FStreamableManager* AssetLoader和物件数据库class UItemInfoDatabase* ItemDatabase
- 使用加载器异步请求加载物件数据库里的物件列表
有个不好的地方就是,绑定加载完的回调指针,不能在获取对应的加载的对象
实现
物件和数据库都在 ItemInfoDatabase.h 中(***++ps++:***如果修改了 FVCharPartInfo,记得要重新启动一下编辑器,否则这个结构体在编辑器中没有变化)
- ItemInfoDatabase.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
USTRUCT()
struct FVCharPartInfo
{
GENERATED_USTRUCT_BODY()
UPROPERTY(EditAnywhere, Category = "DATA")
int32 MeshID;
UPROPERTY(EditAnywhere, Category = "DATA")
TAssetPtr<USkeletalMesh> MeshResource;
FVCharPartInfo()
{
MeshID = 0;
MeshResource = FStringAssetReference("");
}
};
//Holds a dynamic collection of character parts
UCLASS(BlueprintType)
class UItemInfoDatabase : public UDataAsset
{
GENERATED_UCLASS_BODY()
UPROPERTY(EditAnywhere, Category = "Model List") //Exposes the array as editable on editor
TArray<FVCharPartInfo> MeshList;
public:
UItemInfoDatabase();
}; - ItemInfoDatabase.cpp
1
2
3
4
5
6
7ItemInfoDatabase.cpp
UItemInfoDatabase::UItemInfoDatabase(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer)
{
}
- ItemInfoDatabase.h
在Editor中建个UItemInfoDatabase蓝图类
- 在编辑器中把资源引用添加进去,下面的单例类会直接加载这个UitemInfoDatabase载蓝图类
- 添加资源的引用
- 在编辑器中把资源引用添加进去,下面的单例类会直接加载这个UitemInfoDatabase载蓝图类
全局单例类,初始化时把数据库加进去
- SolusDataSingleton.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
struct FStreamableManager;
class UItemInfoDatabase;
UCLASS(Blueprintable, BlueprintType)
class USolusDataSingleton : public UObject
{
GENERATED_BODY()
public:
USolusDataSingleton(const FObjectInitializer& ObjectInitializer);
virtual ~USolusDataSingleton();
static USolusDataSingleton* Get(); // Get method to access this object
struct FStreamableManager* AssetLoader; // Your asset loader
class UItemInfoDatabase* ItemDatabase;
}; - SolusDataSingleton.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
USolusDataSingleton::USolusDataSingleton(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
AssetLoader = new FStreamableManager();
//加载itemDataBase蓝图类
UObject* obj = AssetLoader->SynchronousLoad(FStringAssetReference(TEXT("/Game/TopDownCPP/MeshItems/MeshDateBaseBP")));
ItemDatabase = Cast<UItemInfoDatabase>(obj);
}
USolusDataSingleton::~USolusDataSingleton()
{
if (AssetLoader)
delete AssetLoader;
}
USolusDataSingleton* USolusDataSingleton::Get()
{
USolusDataSingleton* DataInstance = Cast<USolusDataSingleton>(GEngine->GameSingleton); //这里指定配置文件中指定的单例类
if (!DataInstance)
return nullptr;
else
return DataInstance;
}
- SolusDataSingleton.h
在BpLib中起个方法测试异步加载
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31//h
UFUNCTION(BlueprintCallable, Category = "Async Load")
static UObject* TestAsyncLoad(AMyChar* _myChar);
//cpp
bool UMyBpFuncLib::TestAsyncLoad(AMyChar* _myChar)
{
if (!_myChar)
return false;
FStreamableManager* BaseLoader = USolusDataSingleton::Get()->AssetLoader;
UItemInfoDatabase* _database = USolusDataSingleton::Get()->ItemDatabase;
if (!BaseLoader || !_database)
return false;
TArray<FStringAssetReference> ObjToLoad;
for (int32 i = 0; i < _database->MeshList.Num(); ++i)
{
ObjToLoad.AddUnique(_database->MeshList[i].MeshResource.ToStringReference());
}
//请求异步加载
BaseLoader->RequestAsyncLoad(ObjToLoad, FStreamableDelegate::CreateUObject(_myChar, &AMyChar::TestAsyncLoad));
return true;
}
//回调方法
void AMyChar::TestAsyncLoad()
{
FString str = FString::Printf(TEXT("--- AMyChar::TestAsyncLoad callback"));
GEngine->AddOnScreenDebugMessage(0, 5.0f, FColor::Red, str);
}蓝图调用测试方法
结果