B站教學鏈接:https://space.bilibili.com/449549424?spm_id_from=333.1007.0.0 一、引用介紹
虛幻引擎給我們提供了兩種引用,一個是硬引用。軟引用通常是僅儲存資源對象的資源路徑?jīng)]有與資源產(chǎn)生耦合關(guān)系的引用(軟引用加載到內(nèi)存中,引用對象不會被加載到內(nèi)存中,只有在需要的時候才會被加載進內(nèi)存中)。硬引用則是擁有資源對象實際成員變量,直接與資源對象產(chǎn)生耦合(硬引用被加載到內(nèi)存中,則被引用的對象資源也會被加載到內(nèi)存中)。
在UE4開發(fā)中經(jīng)常性需要獲取一些資源(StaticMesh,Material,Particle,Datatable, Actor藍圖,各種繼承UObject的藍圖等等)的路徑,然后利用這些路徑進行資源的加載。
藍圖類資源,也就是BlueprintClass,繼承于UObject并且藍圖化的資源。
?非藍圖類資源:UTexture,UStaticMesh,UParticleSystem,UMaterialInterface這些資源:如紋理,粒子,靜態(tài)網(wǎng)格,材質(zhì)等等。
?二、軟引用
在UE4中,我們常用的軟引用有以下四種?FSoftObjectPath、FSoftClassPath、FSoftObjectPtr、TSubclassOf?這四個。
FSoftObjectPath:翻譯成“軟對象路徑”,也就是在一個(UObject,UStruct,Actor,ActorCompoennt)對象中配置一個具體資源(非藍圖資源和藍圖資源都可以)的路徑,當這個對象被加載的時候,F(xiàn)SoftObjectPath指向的資源未被加載,僅僅是提供了一個路徑。
藍圖中的應用:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Ftr")
FSoftObjectPath AssetObjectPath;
如果我們需要某些特定的資源路徑,可以使用元數(shù)據(jù),meta = (AllowedClasses ="Material,StaticMesh"),他就只會選擇你設(shè)置的類型?,
注意1:FSoftObjectPath用AllowedClasses 只能篩選"Material,StaticMesh,Particle等資源
注意2:Material,StaticMesh類型之間不能有空格
?FSoftClassPath:對藍圖資源的一種弱引用,類似FSoftObjectPath,繼承自FSoftObjectPath,可以說是FSoftObjectPath的進一步封裝,不過這里是藍圖資源,指向了藍圖資源的路徑,通過路徑我們可以手動加載。
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Ftr")
FSoftClassPath AssetClassPath;
本質(zhì)是FSoftClassPath指向的資源的路徑為FSoftObjectPath的指向資源路徑的子集?
TSoftObjectPtr:軟對象指針用于在異步加載并且資源加載完成觸發(fā)回調(diào)函數(shù)的時候獲取資源對應的對象指針用的,畢竟異步加載是無法直接獲取對象指針的。
//軟引用獲得資源對象的指針,僅儲存資源對象的資源路徑?jīng)]有與資源產(chǎn)生耦合關(guān)系的引用
//(軟引用加載到內(nèi)存中,引用對象不會被加載到內(nèi)存中,只有在需要的時候才會被加載進內(nèi)存中)
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Ptr")
TSoftObjectPtr<AActor> softActorobj;
?TSoftClassPtr:檢測藍圖資源加載,獲取藍圖資源對應的指針
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Ptr")
TSoftClassPtr<AActor> softActorClass;
同樣的可以直接用TSoftObjectPtr來獲取UClass的指針,因為UClass本身就是UObject的子類。
三、同步加載
在UE4中使用同步加載RequestSyncLoad和異步加載RequestASyncLoad,就要提到一個類FStreamableManager,用于管理流資產(chǎn)并將其保存在內(nèi)存中的本機類。
第一種同步加載的方式RequestSyncLoad
源碼分析:
TSharedPtr<FStreamableHandle> FStreamableManager::RequestSyncLoad(const FSoftObjectPath& TargetToStream, bool bManageActiveHandle, FString DebugName)
{
return RequestSyncLoad(TArray<FSoftObjectPath>{TargetToStream}, bManageActiveHandle, MoveTemp(DebugName));
}
參數(shù)解釋:
- TargetsToStream要加載的資產(chǎn)磁盤。
- bManageActiveHandle如果為true,管理器將保持流句柄活動,直到顯式釋放。
- DebugName此句柄的名稱,將在調(diào)試工具中報告。
測試案例介紹:
FSoftObjectPath Path2 = FString(TEXT("Texture2D'/Game/StarterContent/Textures/T_Brick_Clay_Beveled_M.T_Brick_Clay_Beveled_M'"));
//注意:在資源未完成加載之前代碼會在這一行暫停運行以等待資源加載完成。
TSharedPtr<FStreamableHandle> SyncStreamableHandle2 = UAssetManager::GetStreamableManager().RequestSyncLoad(Path2);
if (SyncStreamableHandle2)
{
//使用RequestSyncLoad(方法加載單個資源的時候要用GetLoadedAsset來獲得FStreamableHandle中返回的資源。
UTexture2D* Image2 = Cast<UTexture2D>(SyncStreamableHandle2->GetLoadedAsset());
if (Image2)
{
UE_LOG(LogTemp, Warning, TEXT("Image2 is %s"), *Image2->GetName());
}
}
注意:資源的引用在Content Browser中右鍵該資產(chǎn),再選擇Copye?Reference即可復制路徑
結(jié)果:
同步加載資源組:
源碼分析:
/**
* Synchronously load a set of assets, and return a handle. This can be very slow and may stall the game thread for several seconds.
*
* @param TargetsToStream Assets to load off disk
* @param bManageActiveHandle If true, the manager will keep the streamable handle active until explicitly released
* @param DebugName Name of this handle, will be reported in debug tools
*/
TSharedPtr<FStreamableHandle> RequestSyncLoad(TArray<FSoftObjectPath> TargetsToStream, bool bManageActiveHandle = false, FString DebugName = TEXT("RequestSyncLoad Array"));
參數(shù)解釋:
- TargetsToStream要加載的資產(chǎn)磁盤。
- bManageActiveHandle如果為true,管理器將保持流句柄活動,直到顯式釋放。
- DebugName此句柄的名稱,將在調(diào)試工具中報告。
案例測試:?
//同步加載資源組
TArray<FSoftObjectPath> Paths;
Paths.AddUnique(FString(TEXT("Texture2D'/Game/StarterContent/Textures/T_Brick_Clay_Beveled_N.T_Brick_Clay_Beveled_N'")));
Paths.AddUnique(FString(TEXT("Texture2D'/Game/StarterContent/Textures/T_Brick_Clay_New_D.T_Brick_Clay_New_D'")));
//注意:在資源未完成加載之前代碼會在這一行暫停運行以等待資源加載完成。
TSharedPtr<FStreamableHandle> SyncStreamableHandle3 = UAssetManager::GetStreamableManager().RequestSyncLoad(Paths);
if (SyncStreamableHandle3)
{
TArray<UObject*>LoadedAssets;
SyncStreamableHandle3->GetLoadedAssets(LoadedAssets);
if (LoadedAssets.Num() > 0)
{
for (int32 i = 0; i < LoadedAssets.Num(); i++)
{
UTexture2D* Image3 = Cast<UTexture2D>(LoadedAssets[i]);
if (Image3)
{
UE_LOG(LogTemp, Warning, TEXT("Image3 is %s"), *Image3->GetName());
}
}
}
}
注意,使用這個方法加載單個資源的時候要用GetLoadedAsset來獲得FStreamableHandle中返回的資源。?
結(jié)果:
同步加載單個資源LoadSynchronous?,實際上是對RequestSyncLoad的一層封裝
源碼分析:
UObject* LoadSynchronous(const FSoftObjectPath& Target, bool bManageActiveHandle = false, TSharedPtr<FStreamableHandle>* RequestHandlePointer = nullptr);
/** Typed wrappers */
template< typename T >
T* LoadSynchronous(const FSoftObjectPath& Target, bool bManageActiveHandle = false, TSharedPtr<FStreamableHandle>* RequestHandlePointer = nullptr)
{
return Cast<T>(LoadSynchronous(Target, bManageActiveHandle, RequestHandlePointer) );
}
template< typename T >
T* LoadSynchronous(const TSoftObjectPtr<T>& Target, bool bManageActiveHandle = false, TSharedPtr<FStreamableHandle>* RequestHandlePointer = nullptr)
{
return Cast<T>(LoadSynchronous(Target.ToSoftObjectPath(), bManageActiveHandle, RequestHandlePointer));
}
案例測試:
//同步加載單個資源LoadSynchronous
FSoftObjectPath Path =FString(TEXT("Texture2D'/Game/StarterContent/Textures/T_Brick_Clay_Beveled_D.T_Brick_Clay_Beveled_D'"));
UTexture2D* Image = UAssetManager::GetStreamableManager().LoadSynchronous<UTexture2D>(Path,false,nullptr);
if (Image)
{
UE_LOG(LogTemp,Warning,TEXT("Image is %s"),*Image->GetName());
}
結(jié)果:
注意:該方法或許適用于較小對象,但可能會導致主線程長時間停滯。在這種情況下,您將需要使用RequestAsyncLoad,它將異步加載一組資源并在完成后調(diào)用委托。?
四、異步加載?
UE4異步加載RequestAsyncLoad
源碼分析:
/**
* This is the primary streamable operation. Requests streaming of one or more target objects. When complete, a delegate function is called. Returns a Streamable Handle.
*
* @param TargetsToStream Assets to load off disk
* @param DelegateToCall Delegate to call when load finishes. Will be called on the next tick if asset is already loaded, or many seconds later
* @param Priority Priority to pass to the streaming system, higher priority will be loaded first
* @param bManageActiveHandle If true, the manager will keep the streamable handle active until explicitly released
* @param bStartStalled If true, the handle will start in a stalled state and will not attempt to actually async load until StartStalledHandle is called on it
* @param DebugName Name of this handle, will be reported in debug tools
*/
TSharedPtr<FStreamableHandle> RequestAsyncLoad(TArray<FSoftObjectPath> TargetsToStream, FStreamableDelegate DelegateToCall = FStreamableDelegate(), TAsyncLoadPriority Priority = DefaultAsyncLoadPriority, bool bManageActiveHandle = false, bool bStartStalled = false, FString DebugName = TEXT("RequestAsyncLoad ArrayDelegate"));
TSharedPtr<FStreamableHandle> RequestAsyncLoad(const FSoftObjectPath& TargetToStream, FStreamableDelegate DelegateToCall = FStreamableDelegate(), TAsyncLoadPriority Priority = DefaultAsyncLoadPriority, bool bManageActiveHandle = false, bool bStartStalled = false, FString DebugName = TEXT("RequestAsyncLoad SingleDelegate"));
參數(shù)解釋:
- TargetsToStream要加載的資產(chǎn)磁盤。
DelegateToCall委托在加載完成時調(diào)用。將被調(diào)用在下一個Tick,如果資產(chǎn)已加載,或許多秒后。
- Priority優(yōu)先級傳遞給流系統(tǒng),優(yōu)先級高的將首先加載。
- bManageActiveHandle如果為true,管理器將保持流句柄活動,直到顯式釋放。
- bStartStalled如果為true,句柄將以停滯狀態(tài)啟動,并且在調(diào)用StartStalledHandle之前不會嘗試實際異步加載。
- DebugName此句柄的名稱,將在調(diào)試工具中報告。
案例測試
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Test")
TArray<TSoftObjectPtr<UTexture2D>> ObjectPtrs;
TSharedPtr<FStreamableHandle> ASyncStreamableHandle2;
void AsyncLoadCompleted();
藍圖資源配置
//異步加載單個資源
FSoftObjectPath Path4 = TEXT("Texture2D'/Game/StarterContent/Textures/T_Ceramic_Tile_M.T_Ceramic_Tile_M'");
TSharedPtr<FStreamableHandle> ASyncStreamableHandle = UAssetManager::GetStreamableManager().RequestAsyncLoad(Path4);
if (ASyncStreamableHandle)
{
UTexture2D* Image4 = Cast<UTexture2D>(ASyncStreamableHandle->GetLoadedAsset());
if (Image4)
{
UE_LOG(LogTemp, Warning, TEXT("Image4 is %s"), *Image4->GetName());
}
}
//異步加載資源組
TArray<FSoftObjectPath>Paths2;
for (auto item:ObjectPtrs)
{
Paths2.AddUnique(item.ToSoftObjectPath());//ToSoftObjectPath()返回的是一個智能指針
}
ASyncStreamableHandle2 = UAssetManager::GetStreamableManager().RequestAsyncLoad(Paths2, FStreamableDelegate::CreateUObject(this, &AMyActor::AsyncLoadCompleted));
}
void AMyActor::AsyncLoadCompleted()
{
if (ASyncStreamableHandle2)
{
TArray<UObject*>ObjectArray;
ASyncStreamableHandle2->GetLoadedAssets(ObjectArray);
if (ObjectArray.Num()>0)
{
for (int i = 0; i < ObjectArray.Num(); i++)
{
UTexture2D* Image5 = Cast<UTexture2D>(ObjectArray[i]);
UE_LOG(LogTemp, Warning, TEXT("Image5 is %s"), *Image5->GetName());
}
}
}
}
結(jié)果:
異步加載單個資源
異步加載資源組文章來源:http://www.zghlxwxcb.cn/news/detail-429808.html
文章來源地址http://www.zghlxwxcb.cn/news/detail-429808.html
到了這里,關(guān)于【虛幻引擎】UE4 同步和異步資源加載(軟引用)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!