[转载]UE基础—资源浅析

Asset

要了解UE4的资源系统,首先要理解 Asset 到底是个啥。它是一种 "既可以被序列化成文件(.uasset、.umap) 保存在硬盘" , 又可以 "从硬盘加载然后反序列化到内存中(UObject)" 的对象 ,主要用来存贮游戏资源(比如:蓝图,贴图,骨骼,声音,特效等)

从硬盘加载资产文件以后,在内存中就可以把它当作UObject对象使用了;比如:UBlueprint、UTexture2D、USkeletalMesh、 USoundWave 等。你在"Content Browser"中看到的每个资产,都有对应的UObject类

资产既然可以被序列化成文件保存在硬盘,那它是以怎样的格式存储对象呢?打开 Edit Preferences , General->Experimental->Core->Text Asset Format Support (勾选) 。然后随便选中一个蓝图对象,右键 Asset Actions->Export to text format;在当前文件的同目录下,就有个同名的.utxt文件

.utxt就是资源存储的内容

用文本编辑器打开,就可以看到它的一些信息,这些信息是被简化过的,不过也能基本了解当前资源包含的内容。从Exports就可以看出,PlayerCharacter.uasset 包含很多内容,比如:PlayerCharacter(对象),PlayerCharacter_C(蓝图类),Default__PlayerCharacter_C (CDO)等,而这些内容反序列化到内存中也是以UPackage的方式放在一起

Asset总结

Asset就是UE4的资产,有两种形态:平常会以 .uasset、.umap文件的形式趴在硬盘种,而在被需要的时候,就能幻化成内存中的UPackage(描述了资产的全部细节,包括:资产简介,资产包含的对象,资产依赖的其他资产等)

Asset Registry

通过上文,我们对Asset应该有个大概的了解。平常它趴在项目目录下的硬盘中,那我们打开编辑器为啥在Content Browser 能看到所有资源呢?

content browser

难道是打开编辑器,就把所有.uasset加载到了编辑器内?肯定不可能,那它是怎么显示这些资源的简介信息呢,这就是 AssetRegistry 最直观的应用。官方的解释:

The Asset Registryis an editor subsystem which gathers information about unloaded assets asynchronously as the editor loads. This information is stored in memory so the editor can create lists of assets without loading them. The information is authoritative and is kept up to date automatically as assets are changed in memory or files are changed on disk. The Content Browseris the primary consumer for this system, but it may be used anywhere in editor code.

Asset Registry 是一个编辑器子系统,用于收集项目目录下那些没有被加载到内存中的资产的基本信息(主要工作原理就是扫描指定的目录,然后加载资产的 Summary 信息),它会把这些信息存储在内存中,它还会自动监听资产变动(改名,移动到其他目录,删除等操作)从而保持信息准确。因此 Content Browser 可以根据 Asset Registry 的内容,从而把资产显示出来(并未真的加载,只是利用了它的基本信息)

Asset Registry 对我们来说直接用到的地方不多,但是如果你经常做一些编辑器功能开发你可能对它不陌生

void FToolbarModule::StartupModule()
{
	//监听资源保存
	UPackage::PackageSavedEvent.AddRaw(this, &FToolbarModule::AssetSaved);
	//监听资源刷新
	IAssetRegistry::Get()->OnAssetUpdated().AddRaw(this, &FToolbarModule::AssetUpdate);
}

AssetRegistry 扫描资产生成的缓存会保在本地:C:\lingze\TestProject\Intermediate\AssetRegistryCache;打包后也会生成 AssetRegistry.bin文件。在移动设备运行游戏的时候,AssetRegistry 模块启动就会把 AssetRegistry.bin 加载到内存

UE4的技能插件(GAS)默认的 Cue 加载方式,就是通过 AssetRegistry 获取你在 ini 配置的 Cue 路径下的所有资产的 AssetData 然后加载。然而大部分情况下,游戏运行过程中不需要 AssetRegistry(GAS可以重载 Cue 的加载方式),因此如果为了节省运行时内存,可以通过ini中的配置关闭使用

DefaultEngine.ini
[AssetRegistry]
bSerializeAssetRegistry=false
bSerializeDependencies=false
bSerializeNameDependencies=false
bSerializeManageDependencies=false
bSerializePackageData=false

Asset Registry总结

Asset Registry是一个通过扫描收集资产简单信息的系统;主要用途是在编辑器环境下,在 content browser下显示所有资产列表,同时还有下列用处:

  1. 通过它能获取某一个路径下所有资产的基本信息
  2. 能查询资产之间的依赖
  3. 可用于加载资产
  4. 在编辑器功能开发中经常被使用

资源加载

UE4加载资源的顺序是 SerializeSummary->CreateUObject->SerializeUObject->PostLoadUObject,大致过程如下:

  1. 序列化文件头,获取资源的基础信息
  2. 根据头讯息创建对应的C++层面的 UObject
  3. 根据资产数据序列化填充 UObject
  4. 调用PostLoad函数,标志在 UObject 层面的加载已经完毕

而加载方式有哪些呢?

引用加载(同步)

最常用的加载方式,分为硬引用(同步)和软引用(半同步:之所叫半同步是指当前资产不会自动加载,但使用时加载的方式依然是同步)

硬引用就是通过UPROPERTY宏的方式将变量暴露给蓝图,然后蓝图中直接将资产拖入。在当前蓝图被加载到内存的时候,变量对应的资产也会自动加载到内存中

UPROPERTY(EditDefaultsOnly)
AActor* TestObject;

软引用也是通过UPROPERTY宏的方式将变量暴露给蓝图,但是包装了一下,那具体有哪些类型呢?FSoftObjectPath,FSoftClassPath,FSoftObjectPtr,TSoftObjectPtr,TSoftClassPtr,别装了这些内容你肯定迷糊了

Object和Class有啥区别,为啥要整2套API?

  • Object是指对象本身,就是你拿到这个对象就可以直接用 (挂在玩家身上,让它在场景中移动等)
  • Class是指对象的类,一般用它生成新的对象(注意和对象本身做区分)

在MyActor对象内定义如下变量:

//直接引用,相当于蓝图上的 ObjectReference
UPROPERTY(BlueprintReadWrite,EditAnywhere)
AActor* TestObject;
//直接引用,相当于蓝图上的 ClassReference
UPROPERTY(BlueprintReadWrite,EditAnywhere)
UClass* TestClass;
//直接引用,相当于蓝图上的 ClassReference,但是限定了类型只能是Actor
UPROPERTY(BlueprintReadWrite,EditAnywhere)
TSubclassOf<AActor> TestSubClass;

//间接引用
UPROPERTY(BlueprintReadWrite,EditAnywhere)
FSoftObjectPath TestSoftObjectPath;
//间接引用
UPROPERTY(BlueprintReadWrite,EditAnywhere)
FSoftClassPath TestSoftClassPath;
//间接引用,效果相当于蓝图上的 SoftObjectReference
UPROPERTY(BlueprintReadWrite,EditAnywhere)
TSoftObjectPtr<AActor> TestSoftObjectPtr;
//间接引用,效果相当于蓝图上的 SoftClassReference
UPROPERTY(BlueprintReadWrite,EditAnywhere)
TSoftClassPtr<AActor> TestSoftClassPtr;

打开蓝图,能看到变量出现在属性列表内,我们逐一解释:

  • TestObject,在编辑器内不能赋值(不能直接选择对象);一般用来保存某个新生成或者已加载对象,MyActor生命周期内,TestObject 引用的对象不会被 GC
  • TestClass,可在编辑器直接赋值;可以是任意资产类型,一般用来 Spawn 对象,或者传递给函数使用
  • TestSubClass,和 TestClass 功能一样,但是限制了引用的资产类型必须是 Actor
  • TestSoftObjectPath,可在编辑器直接赋值;保存了引用的对象的路径,不会自动加载对象。优点是可以做到用时再加载(TestSoftObjectPath.TryLoad()),蓝图内基本不会用到,因为它没有提供蓝图方法
  • TestSoftClassPath,同上;用来加载类(TestSoftClassPath.TryLoadClass<UObject>())
  • TestSoftObjectPtr,在编辑器内不能赋值(不能直接选择对象);一般用来当作临时变量保存某个对象,TestSoftObjectPtr 引用的对象是否会被GC与MyActor生命周期无关(TestSoftObjectPtr 其实就是对 FSoftObjectPath 和 FWeakObjectPtr 的包装 )
  • TestSoftClassPtr,可以在编辑器直接赋值;软引用某个对象类,与TestSoftObjectPtr功能类似,返回的是UClass(TestSoftClassPtr.Get() 直接返回 UClass* )

构造函数加载(同步)

C++代码内调用,一般不建议使用,因为路径是写死的,不够灵活(只能在构造函数内使用)

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

示例如下( static 关键字一定要带上):

ATestActor::ATestActor(const FObjectInitializer& ObjectInitializer)
{
    static ConstructorHelpers::FClassFinder<AActor> TestClass(TEXT("/Game/BluePrint/TestObj"));  
    static ConstructorHelpers::FObjectFinder<UStaticMesh> TestMesh(TEXT("/Game/BluePrint/TestMesh"));
}

FStreamableManager加载(异步)

本质上是调用 LoadPackageAsync(),提供资产加载接口 LoadSynchronous(本质上是锁主线程然后调用异步接口), RequestAsyncLoad , RequestSyncLoad, 都是通过 FSoftObjectPath 去加载对象;卸载资产接口 Unload,ReleaseHandle

这也是最常用的资产管理接口,因为提供了异步接口因此可以错位加载,让游戏更平滑。很多类用它做内部加载方式,比如:AssetRegistry , UObjectLibrary

StaticLoadObject加载(同步)

本质上是调用 LoadPackage(), 目前用到的地方不多,属于比较老的API。这也是LoadObject,LoadClass这两个API的底层实现

资源管理

UE4 内貌似没有资源管理框架的概念,想怎么用都可以,不过提供了 DataAsset 、AssetManager 这两种组织资产的方式

DataAsset(注意与AssetData的区别)

不知道DataAsset算不算一种资源管理,但它确实也是一种将资源集合在一起的方式。比如:某个英雄会用到的所有资源,可以集合在一个DataAsset内,从而选择不同的英雄的时候,只加载对应的英雄的资源,这样也算实现了简单的资源管理,有如下特点:

  • 需要手动定义DataAsset的数据结构,并且手动添加引用的数据
  • 针对不同资产可定义多个DataAsset
  • 可以被到处使用,类似一个DataTable
  • DataAsset只存储引用,并不同步加载所有数据

AssetManager

AssetManager 可以说是DataAsset的威力加强版,它也是目前官方推荐的资源管理的方式。会根据资产类型依靠 AssetRegistry 来加载对应资产,有如下特点:

  • 可用作UObjectLibrary的替代品
  • 可做到精确的资产加载和释放
  • 配置方式比较灵活(支持蓝图和C++配置)
  • AssetsRegistry的存在也使得登记、获取、过滤、监听资产更为便捷

但是它强依赖 AssetRegistry ,如果在运行时关闭了它或者cook的时候选择不被注册,那么可能导致加载不到资产的情况

总结

本文只是对UE4的资源系统做个简单概述,很多前辈对文章中的内容进行了更深入的讲解,以下就是一些文中使用到的链接,想了解更深入的内容可点击查看

AssetRegistry

AssetManager

资源加载

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
UE(虚幻引擎)是一种流行的游戏开发引擎,它通过路径加载资源。 路径加载资源是指使用文件路径来加载游戏中所需的资源。使用UE开发游戏时,开发者可以通过引擎提供的函数和接口来指定文件的路径,并将其加载到游戏中使用。 UE支持多种资源的路径加载,包括但不限于图片、音频、模型、动画等。在游戏开发过程中,开发者可以使用UE提供的资源浏览器或项目管理器来管理和组织资源文件。通过在路径中指定文件的名称和位置,UE可以准确地加载所需的资源。 路径加载资源的好处是提高了游戏开发的灵活性和可定制性。开发者可以根据需要随时更改资源文件的路径,方便地替换或更新资源。此外,路径加载还可以帮助开发者在游戏中使用外部文件、共享资源等,增加了资源的复用性和拓展性。 虽然UE通过路径加载资源很方便,但也需要开发者注意一些问题。首先,文件路径必须正确设置,否则无法加载资源。其次,过多的文件路径可能导致开发文件的混乱,因此需要良好的组织和管理资源文件。最后,路径加载资源可能增加游戏运行时的加载时间和内存消耗,开发者需要优化加载流程,以提高游戏的性能。 总之,UE通过路径加载资源是一种非常常见和有用的游戏开发技术,它提供了便捷的资源管理和使用方式,使开发者能够更好地实现他们的游戏创意。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值