[UE C++] 资源加载(一) 硬&软引用加载资源

[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中资源的引用 非本人创作,侵权必删
在这里插入图片描述

最后

本文主要介绍了硬引用和软引用,以及软引用其自带的同步加载方式。关于资源的异步加载和更多的同步加载方式,放在下一篇文章来说

参考链接

  • 20
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MustardJim

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值