【UE4】加載資源的方式(八)關於資產引用的各種Path和Ptr介紹
參考資料&原文鏈接
這篇文章是完全轉載的,原文鏈接在這里:https://blog.csdn.net/qq_29523119/article/details/84929384。
在UE4 4.18之后的使用變動
在UE4 4.18版本之前,資源的路徑軟引用采用的是:
FStringAssetReference、FStringClassReference、FAssetPtr、TAssetPtr、TAssetSubclassOf。
UE4. 4.18版本用了另外一套:
FSoftObjectPath、FSoftClassPath、FSoftObjectPtr、TSoftObjectPtr、TSoftClassPtr 。
現在我的版本是UE4 4.26.2,看一眼上面的提到的文件,看一下它們的對應關系:
FStringAssetReference -> FSoftObjectPath
// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreTypes.h"
COMPILE_WARNING("FStringAssetReference has been renamed to FSoftObjectPath, change to #include \"UObject/SoftObjectPath.h\" and rename references")
#include "UObject/SoftObjectPath.h"
FStringClassReference -> FSoftClassPath
// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreTypes.h"
COMPILE_WARNING("FStringClassReference has been renamed to FSoftClassPath and merged headers, change to #include \"UObject/SoftObjectPath.h\" and rename references")
#include "UObject/SoftObjectPath.h"
FAssetPtr -> FSoftObjectPtr
UE_DEPRECATED(4.18, "FAssetPtr was renamed to FSoftObjectPtr as it is not necessarily an asset")
typedef FSoftObjectPtr FAssetPtr;
TAssetPtr -> TSoftObjectPtr
// Not deprecating these yet as it will lead to too many warnings in games
//UE_DEPRECATED(4.18, "TAssetPtr was renamed to TSoftObjectPtr as it is not necessarily an asset")
template<class T=UObject>
using TAssetPtr = TSoftObjectPtr<T>;
TAssetSubclassOf -> TSoftClassPtr
//UE_DEPRECATED(4.18, "TAssetSubclassOf was renamed to TSoftClassPtr")
template<class TClass = UObject>
using TAssetSubclassOf = TSoftClassPtr<TClass>;
在UE4開發中經常性需要獲取一些資源(StaticMesh,Material,Particle,Datatable, Actor藍圖,各種繼承UObject的藍圖等等)的路徑("/Game/......."),然后利用這些路徑進行資源的加載,參考(UE4 4.20)UE4加載資源得到UClass和UObject ----------LoadObject,LoadClass,FStreamableManager)。也可以看本博客前面的幾篇文章,對它們有一個較為詳細的介紹。
藍圖類資源,也就是BlueprintClass,繼承於UObject並且藍圖化的資源,如下所示:

非藍圖類資源:UTexture,UStaticMesh,UParticleSystem,UMaterialInterface這些資源:如紋理,粒子,靜態網格,材質等等,下圖所示:

而資源的加載我們經常性的用到 FSoftObjectPath、FSoftClassPath、FSoftObjectPtr、TSubclassOf 這四個玩意。
FSoftObjectPath
基本使用
翻譯成“軟對象路徑”,也就是在一個(UObject,UStruct,Actor,ActorCompoennt)對象中配置一個具體資源(非藍圖資源和藍圖資源都可以)的路徑,當這個對象被加載的時候,FSoftObjectPath指向的資源未被加載,僅僅是提供了一個路徑:
UPROPERTY(EditAnywhere)
FSoftObjectPath SoftObjectPath;
在編輯器顯示的結果:

獲取路徑:在Content Browser中右鍵該資產,再選擇Copye Reference即可復制路徑,形如:
Texture2D'/Game/UI/Images/InterestingUE4.InterestingUE4'
用AllowedClasses篩選特定資源
我們只需要某種特定資源的路徑,可以用UPROPERTY的Metadata Specifiers -- “AllowedClasses”
UPROPERTY(EditAnywhere, meta = (AllowedClasses ="Material,StaticMesh"))
FSoftObjectPath softObjectPath;

注意AllowedClasses = "Material,StaticMesh" 的 Material和StaticMesh不能有空格,否則會出現編輯器上的bug。
那么可以直接篩選出某種特定的藍圖資源?經我嘗試不行。
FSoftClassPath
對藍圖資源的一種弱引用,類似FSoftObjectPath,不過這里是藍圖資源,指向了藍圖資源的路徑,通過路徑我們可以手動加載。
(同步加載或者異步加載)藍圖資源獲得UClass指針。
看源碼:
/**
*A struct that contains a string reference to a class, can be used to make soft references to classes
*/
struct COREUOBJECT_API FSoftClassPath : public FSoftObjectPath
{
FSoftClassPath()
{ }
FSoftClassPath(FSoftClassPath const& Other)
: FSoftObjectPath(Other)
{ }
FSoftClassPath是繼承FSoftObjectPath,也就是說其實也是指向某種資源的路徑。
基本使用
和上面那個差不多:
UPROPERTY(EditAnywhere)
FSoftClassPath SoftClassPath;

其實FSoftClassPath指向的資源的路徑為FSoftObjectPath的指向資源路徑的子集:

用MetaClass可以篩選一些繼承UObject的藍圖類。
用FSoftClassPath和MetaClass篩選自定義繼承於UObject類的資源
這里說一下,FSoftObjectPath用AllowedClasses 只能篩選"Material,StaticMesh,Particle等資源",像我們自定義繼承UObject的類用AllowedClasses 就無法篩選了。
這時候就需要FSoftClassPath 和 MetaClass,FSoftClassPath也是弱引用,得我們手動利用這個資源進行加載成UClass(異步或者同步)。
比如我是們創建一個繼承AActor的類AMyActor:
UCLASS()
class MYPROJECT6_API AMyActor : public AActor
{
GENERATED_BODY()
}
UCLASS(config=Game)
class AMyProject6Character : public ACharacter
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, meta = (MetaClass = "MyActor"))
FSoftClassPath aaa;
}
看下編輯器:

ToString() 依然是返回藍圖資源的路徑。
FSoftObjectPtr
軟對象指針,作用我在(UE4 4.20)UE4加載資源得到UClass和UObject ----------LoadObject,LoadClass,FStreamableManager已經說過。
用於在異步加載並且資源加載完成觸發回調函數的時候獲取資源對應的對象指針用的,畢竟異步加載是無法直接獲取對象指針的。
示例代碼:
void ATestLoadObjectCharacter::BeginPlay()
{
Super::BeginPlay();
FStreamableManager streamableManager;
FString strMeshFileName = "/Game/Geometry/Meshes/1M_Cube.1M_Cube";
FStreamableDelegate streamableDelegate;
FSoftObjectPath strMeshObjectFileName = FSoftObjectPath(strMeshFileName);
streamableDelegate.BindUObject(this, &ThisClass::LoadFinish, strMeshObjectFileName);
streamableManager.RequestAsyncLoad(strMeshObjectFileName, streamableDelegate);
}
void ATestLoadObjectCharacter::LoadFinish(FSoftObjectPath meshFilePath)
{
FSoftObjectPtr meshObjectPtr = FSoftObjectPtr(meshFilePath);
UObject* pObject = meshObjectPtr.Get();
if (nullptr == pObject)
return;
UStaticMesh* pStaticMesh = Cast<UStaticMesh>(pObject);
if (pStaticMesh)
{
UE_LOG(LogTemp, Error, TEXT("UStaicMesh name is %s"), *pStaticMesh->GetName());
}
}
異步加載的時候綁定一個委托FSteamableDelegate,在委托回調的時候進行對象的獲取,對象指針的獲取是通過 FSoftObjectPtr 對 FSoftObjectPath 的構造。要拿到資源還要使用Get函數:
FSoftObjectPtr meshObjectPtr = FSoftObjectPtr(meshFilePath);
UObject* pObject = meshObjectPtr.Get();
TSoftObjectPtr
TSoftObjectPtr是封裝了FSoftObjectPtr的模板,同樣是用於“在給予文件路徑下檢測一個資源是否已經加載進了內存,獲取資源對應的對象指針”。類似上面的一種寫法,,直接幫我們省掉了“Cast”轉為對象的過程:
TSoftObjectPtr<UStaticMesh> StaticMeshPtr = TSoftObjectPtr<UStaticMesh>(meshFilePath);
UStaticMesh* pStaticMesh = StaticMeshPtr.Get();
if (pStaticMesh)
{
UE_LOG(LogTemp, Error, TEXT("UStaicMesh name is %s"), *pStaticMesh->GetName());
}
TSoftClassPtr
很抱歉我查了下並不存在FSoftClassPtr,UE4直接提供了TSoftClassPtr來檢測藍圖資源加載而成的UClass*。
異步加載藍圖變成UClass*的demo:
void AMyProject7Character::BeginPlay()
{
Super::BeginPlay();
FStreamableManager streamableManager;
FString strBPClassPath = "/Game/testActor.testActor_C";
FStreamableDelegate streamableDelegate;
FSoftClassPath SoftBPClassPathName = FSoftClassPath(strBPClassPath);
streamableDelegate.BindUObject(this, &ThisClass::LoadFinish, SoftBPClassPathName);
streamableManager.RequestAsyncLoad(SoftBPClassPathName, streamableDelegate);
}
void AMyProject7Character::LoadFinish(FSoftClassPath SoftBPClassPathName)
{
TSoftClassPtr<AActor> ActorClassPtr = TSoftClassPtr<AActor>(SoftBPClassPathName);
UClass* pClass = ActorClassPtr.Get();
if (pClass)
{
UE_LOG(LogTemp, Error, TEXT("UStaicMesh name is %s"), *pClass->GetName());
}
}
反正就是跟TSoftObjectPtr類似,只不過TSoftClassPtr是僅僅用於UClass*。
當然你可以直接用TSoftObjectPtr來獲取UClass的指針,因為UClass本身就是UObject的子類,就像TSoftObjectPtr<UClass>。
TSubclassOf
TSubclassOf 作用類似於
UPROPERTY(EditAnywhere)
UClass* actorClass;
不過TSubclassOf是安全類型也帶篩選功能(用模板篩選UObject或者繼承UObject的藍圖類)。
為強引用,就是所在資源加載的時候,這個UClass也跟着加載,就跟一個UStaticMeshComponent 里的 UPROPERTY(EditAnywhere) class UStaticMesh* StaticMesh 是同樣的道理。
UPROPERTY(EditAnywhere)
TSubclassOf<ACharacter> actorClass;
獲取UClass*指針
UClass* pClass = actorClass.Get();
參考資料
【1】http://api.unrealengine.com/INT/API/Runtime/CoreUObject/UObject/FSoftObjectPath/index.html
【2】http://api.unrealengine.com/INT/API/Runtime/CoreUObject/UObject/FSoftObjectPtr/index.html
【3】https://docs.unrealengine.com/en-us/Programming/Assets/AsyncLoading
【4】https://docs.unrealengine.com/en-US/Programming/UnrealArchitecture/Reference/Metadata
【5】https://docs.unrealengine.com/en-US/Programming/UnrealArchitecture/TSubclassOf
本文標簽
游戲開發、游戲開發基礎、Unreal Engine、UE資源加載。
