【UE4】加載資源的方式(九)各種加載方式特點總結和選擇


【UE4】加載資源的方式(九)各種加載方式特點總結和選擇

參考文章&參考資料&原文鏈接

UE4中資源的引用

UE4的資源管理

前面幾篇文章介紹了各種各樣資源的加載方式,現在就來對它們進行一個總結。以后就當工具查了,忘了就回來看一眼。

參考了很多大佬的博客,也自己手動寫代碼感受也一下他們的異同(所有的文章參考了哪部分都有注明),確實資源加載要做到很好的管理不是一件容易的事。這是前面的文章:

【UE4】加載資源的方式(一)使用引用進行簡單加載

【UE4】加載資源的方式(二)使用StaticLoadClass和StaticLoadObject來加載

【UE4】加載資源的方式(三)使用ConstructorHelpers來加載

【UE4】加載資源的方式(四)使用DataAsset引用然后加載

【UE4】加載資源的方式(五)使用ObjectLibrary引用然后加載

【UE4】加載資源的方式(六)使用StreamableManager進行加載

【UE4】加載資源的方式(七)使用AssetManager進行加載

【UE4】08_加載資源的方式(八)關於資產引用的各種Path和Ptr介紹

有關概念

需要了解的概念是:

  • 路徑索引的意義。例如:

    v2-85372c13737c85fa7ade48123dddebcc_720w

  • 引用的概念、作用及其分類,它們的優缺點及適用場景。

  • 資源加載的大致步驟。

  • 同步加載、異步加載、回調函數、靜態加載和動態加載的概念,加載的總入口函數是什么。

  • 常用的資源加載與卸載函數及它們的參數。

  • 主資源、次資源、主資源標簽、資產注冊的概念。

簡單引用

分為軟性引用、硬性引用、構造時引用、強引用和弱引用。

基本方式

UE4 4.18版本之前:

FStringAssetReferenceFStringClassReferenceFAssetPtrTAssetPtrTAssetSubclassOf

UE4. 4.18版本之后:

FSoftObjectPathFSoftClassPathFSoftObjectPtrTSoftObjectPtrTSoftClassPtr

推薦使用最新的引用方式。

特點

  • 對美術師或設計師來說十分友好,他們可以在藍圖中直接使用,可以直接實時預覽效果。
  • 可以考慮使用DataAsset來存儲引用,統一管理。
  • 可以用UPROPERTY()宏的meta = (AllowedClasses ="Material,StaticMesh")篩選UE原生的資源類型,用meta = (MetaClass = "MyActor")則可以篩選自定義繼承UObject的類型。

注意

  • 需要熟悉它們定義和區別,以及它們之間的聯系和區別,例如4.18之前是用的哪幾個,在4.18及之后又改成了什么。

  • 硬性引用資產過大時要注意性能問題。可以考慮用弱引用,然后再在合適的地方異步加載。

  • 有些引用有模板類,十分方便。例如:TSoftObjectPtrTSubclassOf

  • 對於FSoftObjectPath來說:可以使用UPROPERTY(meta=(AllowedClasses="Material,StaticMesh"))來篩選原生的UE4特定的類型。

  • 對於FSoftClassPath來說:要篩選我們自定義繼承UObject的類型可以使用UPROPERTY(meta = (MetaClass = "MyActor"))來篩選。

  • 在使用之前用IsPendingIsValid檢查是否設置了引用以及引用的資源是否已經准備好是一個好習慣。

  • 如果引用是以字符串的形式直接寫在代碼里面的話,例如:

     static ConstructorHelpers::FClassFinder<APawn> PlayerPawnBPClass(TEXT("/Game/ThirdPersonCPP/Blueprints/ThirdPersonCharacter"));
    

    那么在構建版本時,並不會將該引用cook進包中,這是個巨坑,可以考慮使用DataAsset來統一處理。

    如果沒有用DataAsset的話那么就需要手動指定,讓該資源打進包中。在DefaultGame.ini的文件的/Script/UnrealEd.ProjectPackagingSettings標簽的DirectoriesToAlwaysCook數組中配置包含該資源的目錄。例如:

    [/Script/UnrealEd.ProjectPackagingSettings]
    +DirectoriesToAlwaysCook=(Path="/Game/ThirdPersonCPP/Blueprints")
    

    與指定字符串路徑相比,當在編輯器中對被軟引用到的資源進行移動、改名等操作時,ue4會進行自動調整。

  • 強引用是自動加載資源的,弱引用可能已經加載了可能沒加載,如果沒加載的話需要我們手動加載。強引用和弱引用的區別:

    UCLASS(config=Game)
    class AMyTest1Character : public ACharacter
    {
        GENERATED_BODY()
        
        // ... ...
        
    public:
        UPROPERTY(Category = MyTest1, EditAnywhere) TSoftObjectPtr<UTexture2D> SourceTexture1; // 軟引用
        UPROPERTY(Category = MyTest1, EditAnywhere) UTexture2D* SourceTexture2; // 硬引用
    };
    

    在Referece Viewer中,粉色的線為弱引用,白色的線為強引用:

    img

Load

是同步加載資源的一種方式。其中的LoadPackageAsync是整個UE資源加載的大入口。

特點

  • 不論加載的是UObject還是UClass,其本質都是使用路徑加載,即必須知道完整路徑。
  • 支持加載的UObject的類型很多。例如Texture、Material、SoundWave、SoundCue、ParticlesSystem、AnimMontage、BlendSpace(1D,2D,3D)、AnimSequence、AnimBlueprint、SkeletalMesh等等。

注意

  • LoadClassStaticLoadClassLoadObjectStaticLoadObject這幾個函數的聯系與區別。
  • 同步加載注意大資源可能會引起的卡頓和掉幀。
  • 需要路徑不能出錯,藍圖則需要加上_C

ConstructorHelpers

特點

  • 同樣是需要完整路徑的一種加載方式。
  • 只能在構造函數里面使用,非構造函數中使用會引起Error。這適用於某些情況,例如要使用這個資源的時候必須加載另一種資源,這個時候就可以考慮在構造函數中使用ConstructorHelpers。

注意

  • ConstructorHelpers 只能在構造函數中使用。如果在非構造函數中使用的話,則會引起Crash(原因不明),在其代碼內部檢查了是否在構造函數中調用:CheckIfIsInConstructor(ObjectToFind);
  • ConstructorHelpers 前面必須加上static
  • 同樣的,代碼里面的AMyCharacter都可以換成AActor,只是個人更推薦寫AMyCharacter,因為AMyCharacterBP_MyCharacter的最直接的父類。
  • FObjectFinder()是對LoadObject()的封裝。但是FClassFinder()不是對LoadClass()的封裝,FClassFinder()內部調用的是LoadObject()。

DataAsset

UDataAsset包含一個簡單資源數據的基類。如果您繼承了這個類,編輯器將在content browser中列出它。這個相當於Unity Asset文件,可以用來存儲數據。

特點

  • 不過手動定義數據結構的話靈活性極大,並且可以定義多種不同的數據。

  • 這種方式似乎類似於用DataTable數據驅動開發,就像一個配置表一樣。DataTable也需要自定義數據類型。

  • 有了這個不是寫在代碼里的顯示引用,UE就能自動幫我們處理,比如在重定向的時候就會自動處理。

  • 一個DataAsset可以給很多個藍圖使用,只需要使用UPROPOERTY宏。

  • 由於能直觀的的看到引用的數據,因此同樣對設計師或美術師十分友好。例如:

    image-20211104215031211

注意

  • 需要繼承自UDataAsset類,並手動定義DataAsset的數據結構,並且要手動添加需要的數據的引用,稍顯麻煩。
  • DataAsset只是存儲引用,並不是真正的加載數據,加載數據是用的其他方法。

ObjectLibrary

ObjectLibrary:是一個對象,包含了一系列繼承共享基類的未加載對象或者未加載對象的FAssetData 。您可以通過提供一個搜索路徑來加載一個對象庫,它將加載那個路徑中的所有資源。

其實里面就只是放了一個FAssetData

特點

  • 同樣的,他也只是記錄路徑,加載是靠其他方法,當然你要是想用它自帶的方法加載也可以- -。
  • 其內部只是一個DataAsset而已,只不過不一樣的是我們不需要自定義數據結構來記錄資產路徑,而是需要給它一個掃描路徑和掃描類型,那么它就會幫我們記錄,就不用我們一個一個手動的添加了。

注意

  • 需要用CreateLibrary函數來掃描指定的資源類型和資源路徑(注意添加到根節點放置GC)。
  • 再用GetAssetDataList來獲取掃描的結果,傳入一個TArray<FAssetData>的引用來獲得所有的路徑,這個路徑就是傳入掃描的路徑。
  • 最后使用路徑可以按需加載。

StreamableManager

用於管理流資產並將其保存在內存中的本機類。AssetManager是具有藍圖訪問權的全局單例版本。

在UE中可以直接用的寫法:UAssetManager::GetStreamableManager()

核心是一個共享內存指針得到句柄 TSharedPtr<FStreamableHandle>* RequestHandlePointer ,用它來控制資源的釋放。

加載單個資源:LoadSynchronous

同步加載:RequestSyncLoad

異步加載:RequestAsyncLoad

資源卸載:Unload

特點

  • 可以加載單個資源,也可以加載一組資源。
  • 同時支持同步加載和異步加載兩種方式,選擇和控制靈活多變。
  • 使用返回的Handle以控制資源的釋放。

注意

  • 注意同步加載代碼會一直停在那一行等待范圍Handle,而異步加載則有個回調函數以供執行后續操作。
  • 資源加載完畢了要用Get取,第二次調用Get則會取消引用。

AssetManager

需要弄清楚主資源、次資源和主資源標簽的概念。

調用 GetPrimaryAssetId 即可獲得此主資源ID。覆蓋GetPrimaryAssetId函數以讓次資源成為主資源。

ScanPathForPrimaryAssets來掃描路徑列表,讀取指定類型的所有主資產的資產數據。

LoadPrimaryAssetsLoadPrimaryAssetLoadPrimaryAssetsWithType 可用於在適當的時間開始加載主資源。

UnloadPrimaryAssetsUnloadPrimaryAssetUnloadPrimaryAssetsWithType 進行卸載。

資源需要注冊,注冊資源有兩種方式,一種是在引擎里面注冊,一種是在代碼里面注冊。這里需要注意的是數組元素里有一項是PrimaryAssetType,這項的值必須與注冊的資源返回的Id參數AssetType的TEXT值一致。

特點

  • 被認為是UObjectLibrary的替代品,從上面的實踐來說確實很不錯。
  • 確實可以很精確的控制資源的加載和釋放的時機。
  • 配置非常給力精確。
  • AssetsRegistry的存在也使得登記、獲取、過濾、監聽資產更為便捷。

注意

  • 需要覆蓋方法,返回一個ID。使次資源變為主資源。
  • 加載和卸載的函數及參數。
  • 資源注冊的兩種方式以及配置參數。

本文標簽

游戲開發游戲開發基礎Unreal EngineUE資源加載


免責聲明!

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



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