BlueRoseNote/03-UnrealEngine/Gameplay/Gameplay/AssetManager/UPrimaryDataAsset与UAssetManager.md
2023-06-29 11:55:02 +08:00

6.3 KiB
Raw Blame History

GetResourceAcquireProgress 加载进度函数。

文档地址: https://docs.unrealengine.com/zh-CN/Engine/Basics/AssetsAndPackages/AssetManagement/index.html

谁允许你直视本大叔的 的Blog

简述

AssetManager可以使得开发者更加精确地控制资源发现与加载时机。AssetManager是存在于编辑器和游戏中的单例全局对象。

Primary Assets、Secondary Assets与Primary Asset Labels

AssetManagementSystem将资源分为两类PrimaryAssetsSecondaryAssets

PrimaryAssets

PrimaryAssets可以通过调用GetPrimaryAssetId()获取的PrimaryAssetID对其直接操作。

将特定UObject类构成的资源指定PrimaryAssets需要重写GetPrimaryAssetId函数使其返回有效的一个有效的FPrimaryAssetId结构。

SecondaryAssets

SecondaryAssets不由AssetManagementSystem直接处理但其被PrimaryAssets引用或使用后引擎便会自动进行加载。默认情况下只有UWorld关卡Asset )为主资源;所有其他资源均为次资源。

SecondaryAssets设为PrimaryAssets必须重写GetPrimaryAssetId函数返回一个有效的 FPrimaryAssetId结构。

UAssetManager与FStreamableManager

UAssetManager是一个单例对象负责管理主资源的发现与加载。FStreamableManager对象也被包含在其中可以用来执行异步加载资源。通过FStreamableHandle(它是一个智能指针)来控制资源的生命周期(加载与卸载)。

与UAssetManager不同FStreamableManager可以建立多个实例。

AssetBundle

AssetBundle是与主资源相关特定资源的命名列表。使用

meta = (AssetBundles = "TestBundle")

对UObject中的TAssetPtr类型成员变量或FStringAssetReference中的成员变量的UPROPERTY代码进行标记即可完成创建。例如

UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = Display, AssetRegistrySearchable, meta = (AssetBundles = "TestBundle"))
TAssetPtr<UStaticMesh> MeshPtr;
运行时创建
  1. 创建FAssetBudleData结构体对象。
  2. 调用UAssetManager的AddDynamicAsset函数。
  3. 使PrimaryAssets的ID与AssetBundle中的SecondaryAssets关联起来。

从硬盘中加载PrimaryAssets

程序员可以通过继承UPrimaryDataAsset它的父类是UDataAsset拥有加载和保存内置资源束数据的功能的方式来控制ContentBrowser中的AssetPrimaryAssets

下面是一个使用UPrimaryDataAsset的范例它告诉引擎进入什么地图需要什么资源。

/** A zone that can be selected by the user from the map screen */
UCLASS(Blueprintable)
class FORTNITEGAME_API UFortZoneTheme : public UPrimaryDataAsset
{
    GENERATED_UCLASS_BODY()

    /** Name of the zone */
    UPROPERTY(EditDefaultsOnly, Category=Zone)
    FText ZoneName;

    /** The map that will be loaded when entering this zone */
    UPROPERTY(EditDefaultsOnly, Category=Zone)
    TAssetPtr<UWorld> ZoneToUse;

    /** The blueprint class used to represent this zone on the map */
    UPROPERTY(EditDefaultsOnly, Category=Visual, meta=(AssetBundles = "Menu"))
    TAssetSubclassOf<class AFortTheaterMapTile> TheaterMapTileClass;
};
注册PrimaryAssets步骤
如果项目中有自定义的UAssetManager就需要向引擎进行注册

修改引擎目录中的DefaultEngine.ini修改[/Script/Engine.Engine]段中的AssetManagerClassName变量。

[/Script/Engine.Engine] 
AssetManagerClassName=/Script/Module.UClassName

其中“Module”代表项目的模块名“UClassName”则代表希望使用的UClass名。在Fortnite中项目的模块名为“FortniteGame”希望使用的类则名为 UFortAssetManager意味着其 UClass 命名为 FortAssetManager所以第二行应为

AssetManagerClassName=/Script/FortniteGame.FortAssetManager
向UAssetManager注册PrimaryAssets

方法有三: 1.在Project Settings——Game——AssetManager中进入如下设置 image

每个选项的具体功能请参考文档。 2.编辑DefaultGame.ini文件找到或创建一个名为 /Script/Engine.AssetManagerSettings的代码段添加

[/Script/Engine.AssetManagerSettings]
!PrimaryAssetTypesToScan=ClearArray
+PrimaryAssetTypesToScan=(PrimaryAssetType="Map",AssetBaseClass=/Script/Engine.World,bHasBlueprintClasses=False,bIsEditorOnly=True,Directories=((Path="/Game/Maps")),SpecificAssets=,Rules=(Priority=-1,bApplyRecursively=True,ChunkId=-1,CookRule=Unknown))
+PrimaryAssetTypesToScan=(PrimaryAssetType="PrimaryAssetLabel",AssetBaseClass=/Script/Engine.PrimaryAssetLabel,bHasBlueprintClasses=False,bIsEditorOnly=True,Directories=((Path="/Game")),SpecificAssets=,Rules=(Priority=-1,bApplyRecursively=True,ChunkId=-1,CookRule=Unknown))

3.在代码中操作重写UAssetManager类中的StartInitialLoading函数并从该处调用ScanPathsForPrimaryAssets。因此推荐您将所有同类型的主资源放入相同的子文件夹中。这将使资源查找和注册更为迅速。

加载资源

LoadPrimaryAssets、LoadPrimaryAsset和LoadPrimaryAssetsWithType适用于游戏启动前。 之后通过UnloadPrimaryAssets、UnloadPrimaryAsset 和 UnloadPrimaryAssetsWithType卸载。

动态注册与加载PrimaryAsset

//从AssetId构建Asset字符串表并且构建AssetBundle数据
UFortAssetManager& AssetManager = UFortAssetManager::Get();
FPrimaryAssetId TheaterAssetId = FPrimaryAssetId(UFortAssetManager::FortTheaterInfoType, FName(*TheaterData.UniqueId));

TArray<FStringAssetReference> AssetReferences;
AssetManager.ExtractStringAssetReferences(FFortTheaterMapData::StaticStruct(), &TheaterData, AssetReferences);

FAssetBundleData GameDataBundles;
GameDataBundles.AddBundleAssets(UFortAssetManager::LoadStateMenu, AssetReferences);

//通过递归的方式展开AssetBundle数据获取SecondaryAssets数据
AssetManager.RecursivelyExpandBundleData(GameDataBundles);

// 注册动态资源 
AssetManager.AddDynamicAsset(TheaterAssetId, FStringAssetReference(), GameDataBundles);

// 开始预加载
AssetManager.LoadPrimaryAsset(TheaterAssetId, AssetManager.GetDefaultBundleState());