虚幻学习笔记22—C++同步和异步加载

一、前言

        之前提到的静态和动态加载都是同步的加载,同时其中的引用基本都是硬引用。如果资源比较大的话会出现卡顿的现象,下面将介绍一种异步加载的方式。同时,还将介绍一种区别与之前的Load的方法。

        在说明同步和异步加载之前需要先讲一下虚幻引擎的引用路径的问题,虚幻中的资源和类的引用包含软引用和硬引用,硬引用即对象A引用对象B,那么加载对象A的时候会自动加载对象B。软引用,即对象A通过间接机制(一般是字符串形式的路径)来引用对象B,不会在A加载时加载B。静态和动态加载

二、实现

2.1、硬性引用

        比如一个类A中定义一个变量为“输入映射”,在后续的蓝图中添加了,如图2.1.1所示,在细节

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "MyInput")
	class UInputMappingContext* MyMappingContext;
图2.1.1

面板中添加了该变量的具体资源,那么在该类A在加载的同时会自动加载该“输入映射”添加的资源到内存中。

还有一种硬引用的方式,这个函数通常在构造函数中使用。

static ConstructorHelpers::FClassFinder<UUserWidget>tempUICalss(TEXT("/Script/UMGEditor.WidgetBlueprint'/Game/BluePrint/UI3D.UI3D_C'"));
2.2、软引用路径

        而软引用则不同,如下多是在A类中定义以下几个软引用,如图2.2.1所示可以在类A的细节面

	/// <summary>
	/// class的是蓝图类,Object的可以是非类的资源如图片
	/// </summary>
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Path")
	FSoftObjectPath AssetObjectPath;
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Path")
	FSoftClassPath AssetClassPath;
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Path")
	TSoftObjectPtr<AActor> AssetObjectPtr;//场景中的物体
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Path")
	TSoftObjectPtr<AActor> AssetClassPtr;//场景中的物体

板中看到这定义的四个路径,这里的路径绑定的资源不再会A加载的同时加载到内存中,而要通过

图2.2.1

后续的代码再加载到内存中。这就是软引用和硬引用的区别。

2.3、同步加载

        通过复制引用资源的路径,然后添加到代码的的路径中,同步加载在资源比较大的情况下会让主程序都出现卡顿的情况。

	//同步加载
	FSoftObjectPath tempPath2 = TEXT("/Script/Engine.Texture2D'/Game/StarterContent/Textures/T_Wood_Oak_D.T_Wood_Oak_D'");
	TSharedPtr<FStreamableHandle> SynStreamhandle = UAssetManager::GetStreamableManager().RequestSyncLoad(tempPath2);
	if (SynStreamhandle)
	{
		UTexture2D* tempTex2 = Cast<UTexture2D>(SynStreamhandle->GetLoadedAsset());
		if (tempTex2)
		{
			GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Green, FString::Printf(TEXT("TexName:%s"), *tempTex2->GetName()));
		}
	}
2.4、异步加载

        异步加载就是在执行的时候会开启另外一个线程去后台加载资源,因此如果还是通过以下的方式去获取资源可能会不同步得到响应的结果。

	FSoftObjectPath tempPath1 = TEXT("/Script/Engine.Texture2D'/Game/StarterContent/Textures/T_Burst_M.T_Burst_M'");
	//异步加载1
	TSharedPtr<FStreamableHandle>AsyStreamhandle = UAssetManager::GetStreamableManager().RequestAsyncLoad(tempPath1);
	if (AsyStreamhandle)
	{
		UTexture2D* tempTex = Cast<UTexture2D>(AsyStreamhandle->GetLoadedAsset());
		if (tempTex)
		{
			GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Green, FString::Printf(TEXT("TexName:%s"), *tempTex->GetName()));
		}
	}

最好的方式是给异步加载后的结果一个回调函数,如下代码所示,这样在回调函数就可以异步

#include "Engine/StreamableManager.h"

TSharedPtr<FStreamableHandle>AsyStreamhandle;

AsyStreamhandle = UAssetManager::GetStreamableManager().RequestAsyncLoad(tempPath1, FStreamableDelegate::CreateUObject(this, &AMySoftRefActor::AysLoadCallBack));

void AMySoftRefActor::AysLoadCallBack()
{
	if (AsyStreamhandle)
	{
		UTexture2D* tempTex = Cast<UTexture2D>(AsyStreamhandle->GetLoadedAsset());
		if (tempTex)
		{
			GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Green, FString::Printf(TEXT("TexName:%s"), *tempTex->GetName()));
		}
	}
}

处理加载的资源。

三、总结

3.1、软引用和硬引用的区别。

3.2、异步加载最好指定一个回调函数。

猜你喜欢

转载自blog.csdn.net/zhangxiao13627093203/article/details/135204341
今日推荐