【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

參考


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM