[UE C++] 资源加载(一) 硬&软引用加载资源
路径名如何获取
- 对于对象资源,右键Copy Reference
- 对于类资源,右键Copy Reference 然后加上 _C
图片来自于 数据驱动开发
1. 硬引用(Hard Reference)加载
概念: 使用硬引用加载方式,当对象A引用对象B,会导致对象B直接被加载到内存当中。若对象B同时硬引用了对象C,那么对象C也会被加载到内存中,这一过程是递归的,可能会导致短时间内存可用容量迅速降低,进而导致进程卡顿。蓝图的 Cast to XXXX
节点会导致硬引用对象,即使存在但不使用该节点也会硬引用cast对象。所以应该避免在蓝图中大量使用该节点
UPROPERTY(EditDefaultsOnly)
UTexture2D* TextureRef;
UPROPERTY(EditDefaultsOnly)
TSubclassOf<AActor> ActorClassRef;
1.1 构造时引用
通过ConstructorHelpers::FXxxxFinder
实现,只能在构造函数中使用,注意添加static
//加载对象
static ConstructorHelpers::FObjectFinder<UStaticMeshComponent> DoorMesh(TEXT("StaticMesh'/Game/StarterContent/Props/SM_Door.SM_Door'"));
if (DoorMesh.Succeeded())
{
DoorMeshHardRef = DoorMesh.Object;
}
//加载类
static ConstructorHelpers::FClassFinder<AActor> ClassFind(TEXT("Blueprint'/Game/Blueprint/BP_Test.BP_Test'"));
if (ClassFind.Succeeded())
{
ActorClassRef = ClassFind.Class;
}
在以上构造函数中,ConstructorHelpers
类将尝试在内存中查找该资源,如果找不到,则进行加载
1.2 直接属性引用
这是最常见的资源引用情况,将资源通过 UPROPERTY
宏公开。允许设计人员通过蓝图继承对原型指定特定资源,或通过放在环境中的实例来指定该资源
可以和构造时引用一起使用,指定的资源会覆盖构造函数指定的资源
2. 软引用(Soft Reference)加载
概念:
- 对象A通过间接机制(例如字符串形式的对象路径)来引用对象B,软引用对象并不会主动地将引用对象加载到内存当中,需要手动进行同步/异步加载,即软引用并不存放资源本身
- 软引用为间接属性引用,间接属性引用的工作方式对于设计人员就像直接属性引用一样(蓝图中下滑菜单进行选取资源),但是,属性以字符串形式与模版代码存储在一起以便安全地检查资源是否已加载,而不是进行直接指针引用
2.1 FSoftObjectPath
软对象路径,内部存在了一个字符串用于保存引用对象的路径
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
FSoftObjectPath ObjectSoftRef;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, meta = (AllowedClasses = "SkeletalMesh,StaticMesh"))
FSoftObjectPath MeshSoftRef;
注意事项:
- 可用
AllowedClasses
筛选引用对象类型,但是对自定义类型进行筛选会出问题 AllowedClasses
的筛选主要是针对于在Editor中下滑菜单进行选取Object时筛选指定资源,不影响在C++中的使用。换句话说如果AllowedClasses = "SkeletalMesh,StaticMesh"
,但 MeshSoftRef却指定了一个UTexture2D资源,还是可以正常加载并使用
2.1.1 指定引用对象路径
//通过 = ,对象可是FString,FName,FSoftObjectPath对象等
MeshSoftRef = "SkeletalMesh'/Game/Mannequin/Character/Mesh/SK_Mannequin.SK_Mannequin'";
//通过SetPath
MeshSoftRef.SetPath("SkeletalMesh'/Game/Mannequin/Character/Mesh/SK_Mannequin.SK_Mannequin'");
//通过构造函数
FSoftObjectPath MeshSoftRef{ FString("SkeletalMesh'/Game/Mannequin/Character/Mesh/SK_Mannequin.SK_Mannequin'") };
2.1.2 ResolveObject
作用: 判断其引用的资源是否已经载入在内存中,若载入则返还资源对象指针,否则返还空。
//可能为空
TextureRef = Cast<UTexture2D>(ObjectSoftRef.ResolveObject());
2.1.3 TryLoad
作用: 内部调用LoadObject
,尝试在内存中寻找资源,若资源未加载会进行同步加载
//路径未错,会返回UObject指针指向资源
TextureRef = Cast<UTexture2D>(ObjectSoftRef.TryLoad());
2.2 FSoftClassPath
软类路径,继承于 FSoftObjectPath
,专门用于对 UClass* 的软引用
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
FSoftClassPath ClassSoftRef;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, meta = (MetaClass = "Actor"))
FSoftClassPath ActorClassSoftRef;
注意事项:
- 可用
MetaClass
筛选类的范围,对于自定义类型可很好的支持 MetaClass
也只在Editor起作用
2.2.1 指定引用对象路径
由于构造函数和赋值运算符无法继承,所以这里有一点区别存在
//通过构造函数,参数可是UClass,FString,FSoftClassPath
FSoftClassPath ClassSoftRef{"Blueprint'/Game/Blueprint/BP_Test.BP_Test_C'" };
//通过SetPath
ClassSoftRef.SetPath("Blueprint'/Game/Blueprint/BP_Test.BP_Test_C'");
2.2.2 ResolveObject -> ResolveClass
2.2.3 TryLoad -> TryLoadClass
2.3 FSoftObjectPtr
软对象指针,一种指向UObject的弱指针,无法在蓝图中使用,用于异步加载资源过程中,当资源加载完成触发回调函数的时候获取资源对应的对象指针。
FSoftObjectPtr MeshSoftPtr;
struct FSoftObjectPtr : public TPersistentObjectPtr<FSoftObjectPath>
{
······
}
FSoftObjectPtr
就是继承自TPersistentObjectPtr
的智能指针。内部的资源加载逻辑是基于FSoftObjectPath
的二次封装,可使用ToSoftObjectPath()
返回一个FSoftObjectPath
对象
FORCEINLINE const FSoftObjectPath& ToSoftObjectPath() const
{
return GetUniqueID();
}
但是因为返回的是const FSoftObjectPath&
,无法对其引用的资源路径进行修改,只可通过构造函数对其进行初始化指定引用资源路径,或者指定特定UObject对象(CDO对象)
//初始化参数可是UObject,FSoftObjectPath,FSoftObjectPtr
FSoftObjectPtr MeshSoftPtr{ FSoftClassPath {"Blueprint'/Game/Blueprint/BP_Test.BP_Test_C'"}};
注意事项:
FSoftObjectPtr
不能暴露给蓝图FSoftObjectPtr
可以指向UClass,UClass其实就是UObject的子类- 内部实际存在了一个指向资源对象的弱指针
2.3.1 Get()
作用: 获得指向资源的UObject指针,若为空不会触发加载
TextureRef = Cast<UTexture2D>(MeshSoftPtr.Get());
2.3.2 IsPending
作用: Test if this does not point to a live UObject, but may in the future
if(!MeshSoftPtr.IsPending())
{
MeshSoftPtr.Get();
}
2.3.3 IsValid
作用: Test if this points to a live UObject
if(MeshSoftPtr.IsValid())
{
MeshSoftPtr.Get();
}
2.3.4 LoadSynchronous
作用: 返回指向资源的指针,若资源不存在于内存中则进行同步加载(通过FSoftObjectPath::TryLoad
)
TextureRef = Cast<UTexture2D>(MeshSoftPtr.LoadSynchronous());
2.3.5 Reset
作用: Reset the soft pointer back to the null state
MeshSoftPtr.Reset();
2.4 TSoftObjectPtr<>
对FSoftObjectPtr
的模板化,内部逻辑是基于FSoftObjectPtr
的二次封装,可用UProperties
公开给蓝图
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
TSoftObjectPtr<UTexture2D> TextureSoftPtr;
操作与FSoftObjectPtr
基本一致,返回的是指向模板类的指针,减少了手动Cast的步骤
2.5 TSoftClassPtr<>
对FSoftObjectPtr
的模板化,将其转化为UClass*,可用UProperties
公开给蓝图。也可使用TSoftObjectPtr<UClass>
这种形式来代替
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
TSoftClassPtr<AActor> ClassSoftPtr;
操作与FSoftObjectPtr
基本一致,返回的是指向模板类的指针,减少了手动Cast的步骤
软引用关系图
图片来自于 UE4中资源的引用 非本人创作,侵权必删
最后
本文主要介绍了硬引用和软引用,以及软引用其自带的同步加载方式。关于资源的异步加载和更多的同步加载方式,放在下一篇文章来说