UE 资源加载
UE 资源加载
资源引用一般分为资源硬引用和软引用
硬引用:对象 A 引用对象 B,A 加载到内存时B也加载,会导致内存使用量迅速增加。构造时引用:是硬应用的1种,在构造时加载资产并赋给变量。
软引用:仅储存资源对象的资源路径(本质是关联到硬盘上的网络链接),加载A时B不会主动加载到内存中,按需加载。
1 | //硬引用(直接引用) |
LoadObject
一般用来加载资源对象
1 | UMaterial* M_Cube = LoadObject<UMaterial>(nullptr, TEXT("Material'/Game/Geometry/Meshes/CubeMaterial.CubeMaterial'")); |
LoadClass
- 一般用来加载蓝图类, UClass
- 蓝图类的路径末尾加上
_C
1 | UClass* pClass = LoadClass<AActor>(nullptr, TEXT("Blueprint'/Game/CPPFunction/Load/BP_LoadActor.BP_LoadActor_C'")); |
TryLoad
- 配合 FSoftObjectPath 使用
- TryLoad 中调用 LoadObject,加载时需要调用Cast转换一下
1 | FSoftObjectPath SoftObjectPaths_Mesh = FSoftObjectPath(TEXT("StaticMesh'/Game/CPPFunction/Load/StaticMesh.StaticMesh'")); |
TryLoadClass
- 搭配 FSoftClassPath 使用
- TryLoadClass 中调用了 LoadClass
1 | FSoftClassPath SoftClassPath_Actor = FSoftClassPath(TEXT("Blueprint'/Game/CPPFunction/Load/BP_MyActor_SoftRef.BP_MyActor_SoftRef_C'")); |
FStreamableManager::LoadSynchronous
- FStreamableManager::内部调用 RequestSyncLoad
- 参数中返回一个FStreamableHandle类型的指针
可加载非蓝图资源类
- 配合FStreamableManager、FSoftObjectPath 使用
- 配合FStreamableManager、TSoftObjectPtr使用
1 | // 配合 FSoftObjectPath 使用 方法一 |
也可加载蓝图类为 UClass
- 配合FStreamableManager、TSoftObjectPtr使用
- 配合FStreamableManager、TSoftClassPtr使用
1 | FSoftObjectPath SoftObjectPaths_Actor1 = FSoftObjectPath(TEXT("Blueprint'/Game/CPPFunction/Load/BP_MyActor.BP_MyActor_C'")); |
FStreamableManager::RequestSyncLoad
- 配合 FStreamableManager、FSoftObjectPath 使用
- 返回一个FStreamableHandle类型的指针
- TSharedPtr 通过 GetLoadedAsset() 获取单个资源
- TSharedPtr 通过 GetLoadedAssets() 获取多个资源
1 | //加载蓝图并创建 |
异步加载
- 为了避免阻塞主线程,可以使用异步加载的方式来加载资源
- 异步加载完成后,可以设置回调函数
- 创建
FStreamableManager,建议将它放在某类全局游戏单件对象中,如使用GameSingletonClassName在DefaultEngine.ini中指定的对象
FStreamableManager::RequestAsyncLoad
- 返回一个 FStreamableHandle 类型的指针
异步加载非蓝图类资源 FSoftObjectPath
- 单文件加载
1 | //异步加载蓝图并创建 |
多文件加载
方法一 配合
FSoftObjectPtrFSoftObjectPtr是一个结构体,是一种指向UObject的弱指针。无法在蓝图中使用
TSoftObjectPtr是一个模板类,是通用FSoftObjectPtr的模块化包装器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23UPROPERTY(EditAnywhere, Category="SoftObjectPath", meta = (AllowedClasses = "StaticMesh"))
TArray<FSoftObjectPath> ObjectList1;
UFUNCTION()
void OnMultiAssetsLoadFinshed1();
// 函数内部分语句
FStreamableManager& streamableManager = UAssetManager::GetStreamableManager();
FStreamableDelegate streamableDelegate = FStreamableDelegate::CreateUObject(this, &ALoadActor::OnMultiAssetsLoadFinshed1);
streamableManager.RequestAsyncLoad(ObjectList1, streamableDelegate);
// 要回调的函数
void ALoadActor::OnMultiAssetsLoadFinshed1()
{
for (auto AssetItem : ObjectList1)
{
FSoftObjectPtr SoftObjPtr = FSoftObjectPtr(AssetItem); //此处也可用 TSoftObjectPtr<T>
UStaticMesh* mesh = Cast<UStaticMesh>(SoftObjPtr.Get());
if (mesh)
{
UE_LOG(LogTemp, Warning, TEXT("mesh name:%s"), *mesh->GetName());
}
}
}
方法二
配合TSoftObjectPtr<T>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
30UPROPERTY(EditAnywhere, Category = "SoftObjectPath")
TArray<TSoftObjectPtr<UTexture2D>> ObjectList2;
UFUNCTION()
void OnMultiAssetsLoadFinshed2();
// 函数内部分语句
FStreamableManager& streamableManager = UAssetManager::GetStreamableManager();
FStreamableDelegate streamableDelegate;
streamableDelegate.BindUObject(this, &ALoadActor::OnMultiAssetsLoadFinshed2);
TArray<FSoftObjectPath> SoftPathList;
for (int32 i=0; i<ObjectList2.Num(); i++)
{
SoftPathList.Add(ObjectList2[i].ToSoftObjectPath());
}
streamableManager.RequestAsyncLoad(SoftPathList, streamableDelegate);
// 要回调的函数
void ALoadActor::OnMultiAssetsLoadFinshed2()
{
for (auto AssetItem : ObjectList2)
{
UTexture2D* ItemTex = AssetItem.Get();
if (ItemTex)
{
UE_LOG(LogTemp, Warning, TEXT("Texture2D name:%s"), *ItemTex->GetName());
}
}
}异步加载蓝图类
- 单文件加载 FSoftClassPath 、TSoftClassPtr
- 测试
TArray<FSoftClassPath>通过编译
- 测试
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
33
34
35
36
37
38
39
40
41
42
43//加载单个
void AG_LoadHelper::OnLoadASync(const FString loadPath)
{
FSoftObjectPath onloadPath {"Blueprint'/Game/GameBuleprint/TestCube_BP.TestCube_BP_C'"};
FStreamableDelegate hanlde = FStreamableDelegate::CreateLambda([onloadPath]
{
FSoftObjectPtr SoftObjectPtr = FSoftObjectPtr(onloadPath);
UObject *Obj = SoftObjectPtr.Get();
if (IsValid(Obj))
{
UE_LOG(LogTemp,Warning,TEXT("OnLoadASync:%s"),*Obj->GetName())
}
});
UAssetManager::Get().GetStreamableManager().RequestAsyncLoad(loadPath,hanlde);
}
//加载多个蓝图对象
//.h
UPROPERTY(EditAnywhere)
TArray<FSoftObjectPath> ObjectList;
//.cpp
void AG_LoadHelper::OnLoadASync()
{
ObjectList.Add(FSoftObjectPath("Blueprint'/Game/GameBuleprint/TestCube_BP.TestCube_BP_C'"));
ObjectList.Add(FSoftObjectPath("Blueprint'/Game/ThirdPersonBP/Blueprints/ThirdPersonCharacter.ThirdPersonCharacter_C'"));
FStreamableDelegate streamableDelegate = FStreamableDelegate::CreateUObject(this, &AG_LoadHelper::OnSingleAssetLoadFinshed);
UAssetManager::Get().GetStreamableManager().RequestAsyncLoad(ObjectList,streamableDelegate);
}
void AG_LoadHelper::OnSingleAssetLoadFinshed()
{
for (auto path : ObjectList)
{
TSoftClassPtr<AActor> ItemPtr = TSoftClassPtr<AActor>(path);
UClass* ItemClass = ItemPtr.Get();
float height = UKismetMathLibrary::RandomFloatInRange(200,500);
GetWorld()->SpawnActor<AActor>(ItemClass,FVector(0,0,height),FRotator(0,0,0));
UE_LOG(LogTemp, Warning, TEXT("Actor name:%s"), *ItemClass->GetName());
}
}- 单文件加载 FSoftClassPath 、TSoftClassPtr
卸载资源
自动回收
- 当对象失去饮用后会被自动释放。
- 在异步回调结束后,对象会被标记可回收,此时使用
ForceGC可销毁对象
手动回收
在执行加载时,将bManageActiveHandle标记为true,默认为false:表示是否手动管理FStreamableHandle。如果设置为true,则对象会一直常驻内存直到手动释放。
1 | FStreamableManager& AssetLoader = UAssetManager::GetStreamableManager(); |
当对象不再需要时,再手动执行执行Unload。之后对象就会被自动回收:
1 | FStreamableManager& AssetLoader = UAssetManager::GetStreamableManager(); |
Unload之后如果需要立即回收,可以执行ForceGC:
1 | GEngine->ForceGarbageCollection(true); |
通过字符串生成actor
1 | FStringAssetReference asset = "Blueprint'/Game/ThirdPersonBP/Blueprints/ThirdPersonCharacter.ThirdPersonCharacter_C'"; |
UE4 C++入门到进阶] 8.同步or异步资源加载 - 哔哩哔哩