FSoftObjectPath,FSoftClassPath,FSoftObjectPtr,TSoftObjectPtr,TSoftClassPtr在UE4 4.18之后的使用变动
在UE4 4.18版本之前,资源的路径软引用采用的 FStringAssetReference,FStringClassReference,FAssetPtr,TAssetPtr,
TAssetSubclassOf
UE4. 4.18版本用了另外一套: FSoftObjectPath,FSoftClassPath,FSoftObjectPtr,TSoftObjectPtr,TSoftClassPtr
分别对应关系:
// Not deprecating these yet as it will lead to too many warnings in games
//DEPRECATED(4.18, "FStringAssetReference was renamed to FSoftObjectPath as it is now not always a string and can also refer to a subobject")
typedef FSoftObjectPath FStringAssetReference;
//DEPRECATED(4.18, "FStringClassReference was renamed to FSoftClassPath")
typedef FSoftClassPath FStringClassReference;
DEPRECATED(4.18, "FAssetPtr was renamed to FSoftObjectPtr as it is not necessarily an asset")
typedef FSoftObjectPtr FAssetPtr;
// Not deprecating these yet as it will lead to too many warnings in games
//DEPRECATED(4.18, "TAssetPtr was renamed to TSoftObjectPtr as it is not necessarily an asset")
template<class T=UObject>
using TAssetPtr = TSoftObjectPtr<T>;
//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)。
而资源的加载我们经常性的用到 FSoftObjectPath,FSoftClassPath,FSoftObjectPtr,TSubclassOf 这四个玩意
FSoftObjectPath
基本使用
翻译成“软对象路径”,也就是在一个(UObject,UStruct,Actor,ActorCompoennt)对象中配置一个具体资源(非蓝图资源和蓝图资源都可以)的路径,当这个对象被加载的时候,FSoftObjectPath指向的资源未被加载,仅仅是提供了一个路径.
UPROPERTY(EditAnywhere)
FSoftObjectPath softObjectPath;
获取路径:
FString filePath = softObjectPath.ToString();
在编辑器显示的结果
从上面看几乎是可以搜索到UE4内极其多的资源路径(StaicMesh,ParticleSystem,DataTable,各种蓝图类,各种C++类等等)
我们选角色蓝图类,打印路径
void ATestActor::BeginPlay()
{
Super::BeginPlay();
UE_LOG(LogTemp, Error, TEXT("path = %s"), *softObjectPath.ToString());
}
筛选特定资源
我们只需要某种特定资源的路径,可以用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的蓝图类。这里说一下,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());
}
}
FSoftObjectPtr meshObjectPtr = FSoftObjectPtr(meshFilePath);
UObject* pObject = meshObjectPtr.Get();
异步加载的时候绑定一个委托FSteamableDelegate,在委托回调的时候进行对象的获取,对象指针的获取是通过 FSoftObjectPtr 对 FSoftObjectPath 的构造。
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();
参考资料
【3】https://docs.unrealengine.com/en-us/Programming/Assets/AsyncLoading