2種引用方式
硬引用(Hard Reference)
即對象 A 引用對象 B,並導致對象 B 在對象 A 加載時加載
- 硬引用過多會導致運行時很多暫時用不到的資源也被加載到內存中
- 大量資源會導致進程阻塞,致使程序情動事件過長
- 用不大的資源也在內存中,會占用內存
軟引用(Soft Reference)
即對象 A 通過間接機制(例如字符串形式的對象路徑)來引用對象 B
- 軟引用可以減少加載負擔,可以縮短程序啟動時間
- 軟引用不會主動加載到內存中,在需要時加載,用完釋放
藍圖中的資源引用
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();
構造時引用
-
**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++ 中資源的軟引用
- 間接引用並不存放資源本身,本章節主要介紹 FSoftObjectPath、FSoftClassPath、TSoftObjectPtr
- 使用用這種方式需要手動加載資源(同步/異步加載: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();
}
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;
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();
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();
}