前言
与使用LoadObject这种同步加载资源方式不同的是,异步资源加载会开新的线程来进行资源的加载操作,避免因为所需加载资源过大或过多而使主线程卡死。官方文档链接如下:
https://docs.unrealengine.com/latest/CHN/Programming/Assets/AsyncLoading/index.html
但是官方文档介绍的比较笼统,下面我会将我实际使用成功的代码放出来。
同步与异步加载同一套资源
此处我的资源是一组图片。
代码我就只放加载资源的函数了。
同步加载
void LoadData( const FString& path, const FString& namepre, uint16 from, uint16 to )
{
UnLoadData();
FString DataStr;
for (int32 i = from; i <= to; ++i)
{
//此处是拼资源的地址
FString strfmt = FString::Printf( TEXT( "%%s%%s%%0%dd.%%s%%0%dd" ), m_ZeroBit, m_ZeroBit );
DataStr = FString::Printf( *strfmt, *path, *namepre, i, *namepre, i );
//加载资源
UTexture2D* tempTexture = LoadObject<UTexture2D>( NULL, *DataStr );
if( nullptr != tempTexture )
{
tempTexture->AddToRoot();
m_aGifRes.Add( tempTexture );
}
else
{
LOG_OUT( "Load Texture2D : %s Failed!", *DataStr );
}
}
LoadedData();
}
void LoadedData()
{
m_DataLoaded = true;
}
异步加载
异步加载资源需要在类的头文件中加一个FStreamableManager成员,用于管理异步加载线程。
头文件:
TArray<UTexture2D*> m_aGifRes;
TArray<FString> m_Name;//资源路径
FStreamableManager m_Streamable;
void AsyncLoadData( const FString& path, const FString& namepre, uint16 from, uint16 to )
{
UnLoadData();
TArray<FStringAssetReference> itemsToStream;
for( int32 i = from; i <= to; ++i )
{
//拼资源地址
FString strfmt = FString::Printf( TEXT( "%%s%%s%%0%dd.%%s%%0%dd" ), m_ZeroBit, m_ZeroBit );
FString str = FString::Printf( *strfmt, *path, *namepre, i, *namepre, i );
itemsToStream.AddUnique( str );
m_Name.Add( str );
}
//此处调用后文的回调函数
m_Streamable.RequestAsyncLoad( itemsToStream, FStreamableDelegate::CreateRaw( this, &ImageGifPin::AsyncLoadDataDeffered ) );
}
void AsyncLoadDataDeffered()
{
FString DataStr;
for( int32 i = 0; i < m_Name.Num(); ++i )
{
//找到加载成功的资源并添加到预先准备的数组中
UTexture2D* picData = FindObject<UTexture2D>( NULL, *m_Name[i] );
if (nullptr != picData )
{
//防止资源被GC回收
picData->AddToRoot();
m_aGifRes.Add( picData );
}
else if (nullptr == picData )
{
LOG_OUT( "Load %s Failed!!!", picData );
}
}
LOG_OUT( "ImageGifPin Load Completed!!!");
LoadedData();
}
void LoadedData()
{
m_DataLoaded = true;
}