【UE4 C++ 基础知识】<10>资源的引用

2种引用方式

硬引用(Hard Reference)

即对象 A 引用对象 B,并导致对象 B 在对象 A 加载时加载

  • 硬引用过多会导致运行时很多暂时用不到的资源也被加载到内存中
  • 大量资源会导致进程阻塞,致使程序情动事件过长
  • 用不大的资源也在内存中,会占用内存

软引用(Soft Reference)

即对象 A 通过间接机制(例如字符串形式的对象路径)来引用对象 B

  • 软引用可以减少加载负担,可以缩短程序启动时间
  • 软引用不会主动加载到内存中,在需要时加载,用完释放

蓝图中的资源引用

image

image

image

C++ 中资源的硬引用

直接属性引用

引用资源的最简单方法是创建指针,并通过 UPROPERTY 宏公开。这样允许设计人员通过蓝图继承对原型指定特定资源,或通过放在环境中的实例来指定该资源

UPROPERTY(VisibleAnywhere)
	UStaticMeshComponent* body; 

UPROPERTY(VisibleAnywhere)
	class UPhysicsThrusterComponent* upThrusterComp; //class 不需要添加对应头文件,cpp使用时再添加

TSubclassOf 与 UClass

TSubclassOf 与 UClass 类似,但 TSubclassOf 是安全类型,同时具有筛选功能,

UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Class")
	UClass* ClassRef;

UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Class")
	TSubclassOf<AActor>  ActorClassRef;

// 获取UClass* 指针
ClassRef = ActorClassRef.Get();

image

构造时引用

  • **ConstructorHelpers::FObjectFinder<T>** 一般用来加载非蓝图资源

  • **ConstructorHelpers::FClassFinder<T>** 一般用来加载蓝图资源并获取蓝图Class

    • 蓝图文件路径_C,如 Blueprint'/Game/CPPFunction/Load/BP_MyActor.BP_MyActor_C'

    • 蓝图文件去掉后缀,如 Blueprint'/Game/CPPFunction/Load/BP_MyActor'

  • FObjectFinder 和 FClassFinder构造函数都是调用LoadObject()

  • 只能在类的构造函数中使用,否则会crash

  • 变量名必须是 static 类型,也可以使用 auto

// 构造函数
// FObjectFinder 方法一
auto paddleMesh = ConstructorHelpers::FObjectFinder<UStaticMesh>(TEXT("StaticMesh'/Game/Demo_Drone/SM/paddle.paddle'"));
if (paddleMesh.Object != nullptr)
{
	paddle1->SetStaticMesh(paddleMesh.Object);
}

//FObjectFinder 方法二
static ConstructorHelpers::FObjectFinder<UStaticMesh> paddleMesh(TEXT("StaticMesh'/Game/Demo_Drone/SM/paddle.paddle'"));
if (paddleMesh.Succeeded())
{
	paddle1->SetStaticMesh(paddleMesh.Object);
}

// FClassFinder
static ConstructorHelpers::FClassFinder<AActor> BPClassFinder(TEXT("Blueprint'/Game/CPPFunction/Load/BP_MyActor'"));
if (BPClassFinder.Succeeded()) //或者使用 BPClassFinder.Class != nullptr 判断
{
	UClass* MyActorClass = BPClassFinder.Class.Get();
	TSubclassOf<AActor>BP_MyActorClass = BPClassFinder.Class;
	UE_LOG(LogTemp, Warning, TEXT("class name:%s"),*BP_MyActorClass->GetName());
}

C++ 中资源的软引用

  • 间接引用并不存放资源本身,本章节主要介绍 FSoftObjectPathFSoftClassPathTSoftObjectPtr
  • 使用用这种方式需要手动加载资源(同步/异步加载:LoadObject, StaticLoadObject, FStreamingManager)

FSoftObjectPath

  • FSoftObjectPath 是一个简单的结构体,其中有一个字符串包含资源的完整名称。

  • FSoftObjectPath.SolveObject() 可以检查其引用的资源是否已经载入在内存中,若载入则返还资源对象指针,否则返还空。

  • FSoftObjectPath.Reset() 重置软引用为空

  • AllowedClasses meta标签可以筛选资源类型

    • 筛选自定义类 类型时,只能指定放置在 level 中的物体实例,不推荐
// .h 文件
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "SoftObject", meta = (AllowedClasses = "SkeletalMesh, StaticMesh" ))
	FSoftObjectPath SoftObjectPath1;

UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "SoftObject", meta = (AllowedClasses = "Texture2D"))
	FSoftObjectPath SoftObjectPath2;

UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "SoftObject", meta = (AllowedClasses = "Blueprint Class"))
	FSoftObjectPath SoftObjectPath3;

UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "SoftObject", meta = (AllowedClasses = "Drone")) //自定义类型 不推荐
	FSoftObjectPath SoftObjectPath4;
// .cpp文件
void ADrone::BeginPlay()
{
	Super::BeginPlay();

	if (SoftObjectPath1.IsValid()){ /* 处理*/ }
	if (SoftObjectPath2.IsNull()){ /* 处理*/ }
	if (SoftObjectPath3.IsAsset()){ /* 处理*/ }
	FString SoftObjectPath4_AssetName = SoftObjectPath4.GetAssetName();			
	FString SoftObjectPath3_AssetPath = SoftObjectPath3.GetAssetPathString();
}

image

image

FSoftClassPath

  • FSoftClassPath 继承自 FSoftObjectPath,用于存储一个类型的软引用

  • MetaClass meta标签可以筛选类类型

  • FSoftClassPath 继承自 FSoftObjectPath,因此用法与 FSoftObjectPath 差不多

// .h 文件
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "SoftObjectClass")
	FSoftClassPath SoftClassPath;

UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "SoftObjectClass", meta = ( MetaClass= "Pawn"))
	FSoftClassPath SoftClassPath_Pawn;

UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "SoftObjectClass", meta = (MetaClass = "Drone"))
	FSoftClassPath SoftClassPath_Drone;

image

TSoftObjectPtr<T>

  • TSoftObjectPtr 基本上是包含了 FSoftObjectPath 的 TWeakObjectPtr,是智能指针的一种

  • TSoftObjectPtr 与蓝图中的 SoftObjectReference 是一回事

  • 可用于在异步加载完成触发回调函数时,获取资源对应的对象指针

  • TSoftObjectPtr.IsPending() 方法可检查资源是否已准备好可供访问

  • TSoftObjectPtr.Get() 如果被引用资源存在于内存中,将返回这个资源

// .h 文件
// 目前使用4.26,不加 <T> 编译不通过
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "SoftObjectPtr")
	TSoftObjectPtr<UObject> SoftObjectPtr1;

UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "SoftObjectPtr")
	TSoftObjectPtr<UObject> SoftObjectPtr2;

UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "SoftObjectPtr")
	TSoftObjectPtr<UTexture2D> SoftObjectPtr_Texture2D;
// .cpp 文件 BeginPlay() 函数内 
SoftObjectPtr2 = TSoftObjectPtr<AActor>(SoftObjectPath3); //可用 FSoftObjectPath 参数初始化

//此处资源未加载,因而判断为false
if (SoftObjectPtr_Texture2D.IsPending()) 
{
	//获取资源
	UTexture2D* MyTexture = SoftObjectPtr_Texture2D.Get();
}

//转换成 FSoftObjectPath
FSoftObjectPath AActorSoftPath1 = SoftObjectPtr_Texture2D.ToSoftObjectPath();

image

TSoftClassPtr<T>

  • 获取类的软引用,转成 UClass*
// .h
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "SoftClassPtr")
	TSoftClassPtr<AActor> SoftClassPtr_Actor;

UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "SoftClassPtr")
	TSoftClassPtr<ADrone> SoftClassPtr_Drone;

UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "SoftClassPtr")
	TSoftClassPtr<UUserWidget> SoftClassPtr_UserWidget;
// .cpp 

if (SoftClassPtr_Actor.IsPending())
{
	UClass* MyActor = SoftClassPtr_Actor.Get();
}

image

参考

posted @ 2021-04-26 21:22  砥才人  阅读(3731)  评论(0编辑  收藏  举报