首页 > 其他分享 >Unreal Engine 5.2 .uasset文件格式分析

Unreal Engine 5.2 .uasset文件格式分析

时间:2023-08-09 21:22:53浏览次数:34  
标签:Engine Int32 5.2 void 文件格式 FName cpp 区块 TArray

     以下内容只包含UE5的5.2版本,不包含兼容性内容,不同版本可能会有所不同。

提示:

    N  :通常代表数组个数

    ?  :代表不确定,比如字符串的长度。

    *  : 乘积

    Type Name : Size : 此说明并非定义位域,是在说明此处的数据类型、名称以及空间占用,空间单位为字节。

基础类型序列化

       这里对基础类型的序列化进行简单描述,后续的段落中,可能会引用此段落的信息。

类型

细节

参考代码

FString

字符串序列化有一定的特殊性:

基于字符串自身是否以Unicode保存,其占用的大小并不一致。如若全是Ansi字符,则其大小为:

Int32 Num : 4 +

Num * sizeof(ANSICHAR)

Num包含字符串终止符’\0’

 

如果是Unicode保存,则将字符个数以负数保存。然后输出UTF16字符串。

Int32 -Num : 4 + Num * sizeof(UTF16CHAR),同样包含终止符

 

String.cpp

FArchive& operator<<( FArchive& Ar, FString& A )

FName

序列化时会输出两个Int32,其内容为Name数组中的索引+FName的Number属性。

大小为8

可以根据这个索引在NameMap中找到具体值

LinkerSave.cpp

FArchive& FLinkerSave::operator<<( FName& InName )

 

FGuid

4个Int32,大小为16

 

TArray<T>

以Num(int32)开头,后面接所有数组元素自身的序列化数据。

 

FCustomVersion

Int32 NumElements : 4

[

  {

FGuid Key : 16,

Int32 Version: 4

  }

]

以数组个数开头,接着是指定个数的 FCustomVersion,其为20个字节。

这些版本是对于这个资产中某一类数据的版本号标记。

参考:Source/Runtime/Core/Public/UObject/xxxObjectVersion.h

CustomVersion.cpp

FArchive& operator<<(FArchive& Ar, FCustomVersion& Version)

void operator<<(FStructuredArchive::FSlot Slot, FCustomVersion& Version)

FEngineVersion

一个输出5个字段:

UInt16 Major : 2

UInt16 Minor : 2

UInt16 Patch : 2

UInt32 ChangeList : 4

FString Branch : 4 + ?

 

因此总大小为14 + ? 至少14个字节。

 

EngineVersion.cpp

void operator<<(FStructuredArchive::FSlot Slot, FEngineVersion &Version)

FCompressedChunk

FCompressThunk输出4个字段:

Int32 UncompressedOffset : 4

Int32 UncompressedSize : 4

Int32 CompressedOffset : 4

Int32 CompressedSize : 4

Linker.cpp

FArchive& operator<<(FArchive& Ar,FCompressedChunk& Chunk)

FGenerationInfo

两个字段:

Int32 ExportCount : 4

Int32 NameCount : 4

Linker.cpp

void FGenerationInfo::Serialize(FArchive& Ar, const struct FPackageFileSummary& Summary)

FNameEntryId

以FNameEntrySerialized对象的形式保存。输出三个信息:

FString Str : 4 + ?

UInt16 NonCasePreservingHash : 2  // 读取时忽略

UInt16 CasePreservingHash : 2 // 读取时忽略

所以总大小为:8 + ?

UnrealNames.cpp

void FNameEntry::Write( FArchive& Ar ) const

FArchive& operator<<(FArchive& Ar, FNameEntrySerialized& E)

 

FSoftObjectPath

软引用对象在保序列化时根据应用场景不同而不同,当处于文件头时,直接输出两个属性:

FTopLevelAssetPath AssetPath;

FString SubPathString;

 

FTopLevelAssetPath又由两个FName组成:

FName PackageName : 8;

FName AssetName : 8;

 

所以一个软引用的大小为:16 + 4 + ?

TopLevelAssetPath.h

friend FArchive& operator<<(FArchive& Ar, FTopLevelAssetPath& Path)

 

LinkerSave.cpp

FArchive& FLinkerSave::operator<<(FSoftObjectPath& SoftObjectPath)

 

SoftObjectPath.cpp

void FSoftObjectPath::SerializePath(FArchive& Ar)

 

FTextSourceSiteContext

FString KeyName : 4 + ?

FString SiteDescription : 4 + ?

Bool IsEditorOnly : 4

Bool IsOptional : 4

FLocMetadataObject InfoMetaData : 4 + ?

FLocMetadataObject KeyMetaData : 4 + ?

 

GatherableTextData.cpp

void operator<<(FStructuredArchive::FSlot Slot, FTextSourceSiteContext& This)

 

 

FLocMetadataObject

Int32 ValueCount : 4

TMap< FString, TSharedPtr<FLocMetadataValue> > Values : ?

 

InternationalizationMetadata.cpp

void SerializeLocMetadataValue(FStructuredArchive::FSlot Slot, TSharedPtr<FLocMetadataValue>& Value)

 

FTextSourceData

FString SourceString : 4 + ?

FLocMetadataObject SourceStringMetaData : ?

GatherableTextData.cpp

void operator<<(FStructuredArchive::FSlot Slot, FTextSourceData& This)

 

FGatherableTextData

FString NamespaceName : 4 + ?

FTextSourceData SourceData : 8 + ?

TArray<FTextSourceSiteContext> SourceSiteContexts : 4 + ?

GatherableTextData.cpp

void operator<<(FStructuredArchive::FSlot Slot, FGatherableTextData& This)

 

 

FObjectImport

FName ClassPackage : 8

FName ClassName : 8

FPackageIndex OuterIndex : 4

FName ObjectName : 8

FName PackageName : 8 (EditorOnly)

Bool bImportOptional : 4

总大小 40 (Editor) 32(Runtime)

 

ObjectResource.cpp

void operator<<(FStructuredArchive::FSlot Slot, FObjectImport& I)

 

FObjectExport

FPackageIndex ClassIndex : 4

FPackageIndex SuperIndex : 4

FPackageIndex TemplateIndex : 4

FPackageIndex OuterIndex : 4

FName ObjectName : 8

UInt32 ObjectFlags : 4

Int64 SerialSize : 8

Int64 SerialOffset : 8

Bool bForcedExport : 4

Bool bNotForClient : 4

Bool bNotForServer : 4

Bool bIsInheritedInstance : 4

UInt32 PackageFlags : 4

Bool bNotAlwaysLoadedForEditorGame : 4

Bool bIsAsset : 4

Bool bGeneratePublicHash : 4

Int32 FirstExportDependency : 4

Int32 SerializationBeforeSerializationDependencies : 4

Int32 CreateBeforeSerializationDependencies : 4

Int32 SerializationBeforeCreateDependencies : 4

Int32 CreateBeforeCreateDependencies : 4

 

总大小: 96

 

ObjectResource.cpp

void operator<<(FStructuredArchive::FSlot Slot, FObjectExport& E)

FObjectThumbnail

Int32 ImageWidth : 4

Int32 ImageHeight : 4

TArray<UInt8> CompressedImageData : 4 + ?

ObjectThumbnail.cpp

void FObjectThumbnail::Serialize(FStructuredArchive::FSlot Slot)

 

FPropertyTag

FName Name : 8

FName Type : 8

Int32 Size : 4

Int32 ArrayIndex : 4

TagType == Struct:

FName StructName : 8

FGuid StructGuid : 16

TagType == Bool:

UInt8 BoolVal : 1

TagType == Byte or Enum:

FName EnumName : 8

TagType == Array or Set:

FName InnerType : 8

TagType == Map:

FName InnerType : 8

Fname ValueType : 8

 

UInt8 HasPropertyGuid : 1

HasPropertyGrid == 1:

    FGuid PropertyGruid : 16

   

总大小:25 + ?

PropertyTag.cpp

void operator<<(FStructuredArchive::FSlot Slot, FPropertyTag& Tag)

FLookupTableEntry

FIoHash Identifier : 20

Int64 OffsetInFile : 8

UInt64 CompressedSize : 8

UInt64 RawSize : 8

总大小:44 + ?

 

FPackageTrailer::FHeader

UInt64 Tag : 8

Int32 Version : 4

UInt32 HeaderLength : 4

UInt64 PayloadsDataLength : 8

Int32 NumPayloads : 4

TArray<FLookupTableEntry> PayloadLookupTable : (44+?)*NumPayloads

 

总大小:28 + (44+?)*NumPayloads

 

FPackageTrailer::FFooter

UInt64 FooterTag : 8

UInt64 TrailerLength : 8

UInt32 PackageTag : 4

总大小:20

FooterTag = 0x29BFCA045138DE76

#define PACKAGE_FILE_TAG            0x9E2A83C1

 

 

文件头

       文件头部分也分成多个部分,概要部分保存了版本信息以及各种区块的偏移值。保存Package时,会先输出一个不完整的文件头用于占位,在完成所有序列化后,会重新刷新文件头中的数据。

概要

       类型:FPackageFileSummary

       相关代码:

LinkerLoader.cpp : FLinkerLoad::ELinkerStatus FLinkerLoad::ProcessPackageSummary(TMap<TPair<FName, FPackageIndex>, FPackageIndex>* ObjectNameWithOuterToExportMap)

           SavePackage2.cpp : ESavePackageResult WritePackageHeader(FStructuredArchive::FRecord& StructuredArchiveRoot, FSaveContext& SaveContext)

           PackageFileSummary.cpp : void operator<<(FStructuredArchive::FSlot Slot, FPackageFileSummary& Sum)

   

名称

类型

大小

注解

Tag

Int32

4

文件标识

#define PACKAGE_FILE_TAG          0x9E2A83C1

#define PACKAGE_FILE_TAG_SWAPPED    0xC1832A9E

 

LegacyFileVersion

Int32

4

文件版本,当前默认0xFFFFFFF8(-8)

LegacyUE3Version

Int32

4

0x00000360

读取后不再使用

FileVersionUE4

Int32

4

0x0000020a

FileVersionUE5

Int32

4

0x000003f1

FileVersionLicenseeUE4

Int32

4

0x00000000

CustomVersions

TArray<FCustomVersion>

4 + 20 * N

FCustomVersion包含一个FGuid(16字节)作为Key,一个Int32(4字节)作为版本号

TotalHeaderSize

Int32

4

文件头总大小

PackageName

FString

4 + ?

包名称

字符串数据由字符串长度+字符串数据本身组成 包含字符串结束符

PackageFlags

UInt32

4

包标记位

Cooked标记即放在这个字段

NameCount

Int32

4

名字列表的个数

NameOffset

Int32

4

指向名字列表数据区块的偏移值

名字列表是TArray<FNameEntryId>

后续数据中的字符串都只保存这个列表的索引,这样当存在多个相同的字符串时,也只存在一份字符串实例

SoftObjectPathsCount

Int32

4

软引用个数

SoftObjectPathsOffset

Int32

4

软引用数据区块偏移

数据是TArray<FSoftObjectPath>

这以一个路径引用代替真实的对象引用,相当于是一种Lazy处理资源引用的方法,但是对于程序外观来说,与直接硬引用类似。

LocalizationId

FString

4 + ?

本地化标识

GatherableTextDataCount

Int32

4

本地化文本数据个数

GatherableTextDataOffset

Int32

4

本地化文本数据区块偏移

TArray<FGatherableTextData>

使用FText之类的属性时,会产生这个数据。

ExportCount

Int32

4

导出表数据个数

ExportOffset

Int32

4

导出表数据区块偏移

ImportCount

Int32

4

导入表数据个数

ImportOffset

Int32

4

导入表数据区块偏移

 

DependsOffset

Int32

4

依赖数据区块偏移

SoftPackageReferencesCount

Int32

4

 

SoftPackageReferencesOffset

Int32

4

 

SearchableNamesOffset

Int32

4

 

ThumbnailTableOffset

Int32

4

 

Guid

FGuid

16

 

PersistentGuid

FGuid

16

EditorOnly

GenerationCount

Int32

4

 

Generations

FGenerationInfo

8*GenerationCount

 

SavedByEngineVersion

FEngineVersion

14+ ?

 

CompatibleWithEngineVersion

FEngineVersion

14+ ?

 

CompressionFlags

UInt32

4

 

CompressedChunks

TArray<FCompressedChunk>

4 + 16 * N

 

PackageSource

UInt32

4

 

AdditionalPackagesToCook

TArray<FString>

4 + ? * N

Deprecated,新版本中为空

AssetRegistryDataOffset

Int32

4

 

BulkDataStartOffset

UInt64

8

 

WorldTileInfoDataOffset

Int32

4

 

ChunkIDs

TArray<Int32>

4 + 4 * N

 

PreloadDependencyCount

Int32

4

预加载依赖项数量,没有时为-1

PreloadDependencyOffset

Int32

4

预加载依赖项数据区块偏移,始终有值但仅当PreloadDependencyCount有效时才有意义,否则该位置为其它数据

NamesReferencedFromExportDataCount

Int32

4

 

PayloadTocOffset

Int64

8

指向文件尾

文件尾数据主要用于校验

DataResourceOffset

Int32

4

Cooking时才会输出的数据,在导出表后面。这是它的偏移值。

 

区块

       每个区块的大小都是不确定的,但是每个区块在概要数据中最终都会保存对应的偏移值,所以可以基于偏移值直接计算出某个区块的整体大小。

 

名称

类型

大小

注解

NameMap

TArray<FNameEntryId>

(8 + ?)*N

NameOffset、NameCount

字符串列表

 

SoftObjectPathList

TArray<FSoftObjectPath>

(20 + ?)*N

SoftObjectPathsOffset、

SoftObjectPathsCount

GatherableTextData

TArray<FGatherableTextData>

? * N

GatherableTextDataOffset、

GatherableTextDataCount

ImportMap

TArray<FObjectImport>

40 * N

ImportCount、ImportOffset

ExportMap

TArray<FObjectExport>

96 * N

ExportCount、ExportOffset

DependsMap

TArray<TArray<FPackageIndex>>

(4+4) * N

DependsOffset

DependsMap和ExportMap的大小必须是一模一样的,所以不再需要额外的DependsCount

SoftReferences

TArray<FName>

8 * N

SoftPackageReferencesOffset、SoftPackageReferencesCount

SearchableNames

TMap<FPackageIndex, TArray<FName>>

4 + (4 + (4+8*N1))*N2

SearchableNamesOffset

Thumbnails

TArray< FObjectFullNameAndThumbnail >

(12+?)*N + ((4+?)+(4+?)+4)*N

ThumbnailTableOffset

 

SavePackageUtilities.cpp

void SaveThumbnails(UPackage* InOuter, FLinkerSave* Linker, FStructuredArchive::FSlot Slot)

 

分两部分保存。

第一个循环保存TArray< FObjectThumbnail >;

第二个循环保存TArray< FObjectFullNameAndThumbnail>,其中每个FObjectFullNameAndThumbnail保存:

FString ObjectClassName : 4 + ?

FString ObjectPathWithoutPackageName : 4 + ?

Int32 FileOffset : 4

 

AssetRegistry

TArray<UObject::FAssetRegistryTag>

 

?

AssetRegistryDataOffset

SavePackageUtilities.cpp

UE::AssetRegistry::WritePackageData

 

WorldLevelInfo

FWorldTileInfo

?

WorldTileInfoDataOffset

SavePackageUtilities.cpp

void SaveWorldLevelInfo(UPackage* InOuter, FLinkerSave* Linker, FStructuredArchive::FRecord Record)

 

如果不存在这个数据,则WorldTileInfoDataOffset为0

PreloadDependencies

 

?

PreloadDependencyOffset、PreloadDependencyCount

 

CookedOnly

       文件头整体大小保存在TotalHeaderSize中。

 

对象数据

       即Exports。Exports保存的即是对象本身。数据来自TArray<FObjectExport>,FObjectExport中的Object为要保存的对象。其内部具体内容与格式,由Object自行决定。FObjectExport的字段SerialOffset、SerialSize保存在文件头中,可以用于定位每个Export对象的偏移和整体大小。

    序列化单个Object时,默认使用TaggedProperties序列化各个属性。当使用TaggedProperties序列化时,每个属性序列化之前都会与默认值进行比对,当属性值与默认值相同时,该属性会被忽略。每个属性在序列化之前,会输出FPropertyTag,这个Tag用于标记当前区块对应的是哪个属性。读取时,先读取Tag,再通过这个Tag的数据将接下来的内容与目标属性关联在一起。参考代码:

Class.cpp :

void UStruct::SerializeVersionedTaggedProperties(FStructuredArchive::FSlot Slot, uint8* Data, UStruct* DefaultsStruct, uint8* Defaults, const UObject* BreakRecursionIfFullyLoad) const

 

BulkData

       由BulkDataStartOffset定位位置。如果没有时,大小为0。

 

额外数据

名称

类型

大小

注解

AdditionalDataToAppend

TArray<AdditionalDataCallback>

0 or ?

允许通过回调添加自定义数据

SidecarDataToAppend

TArray<FSidecarStorageInfo>

0 or ?

提供给FEditorBulkData添加自定义数据

AdditionalFilesFromExports

TArray<FLargeMemoryWriter, TInlineAllocator<4>>

0 or ?

来自Export的自定义数据,Cookedonly

Tag

UInt32

4

一个终结Tag:

       #define PACKAGE_FILE_TAG          0x9E2A83C1

 

 

文件尾

       以PayloadTocOffset定位,这是最后一个区块。

名称

类型

大小

注解

Header

FPackageTrailer::FHeader

28 + (44+?)*NumPayloads

 

LocalEntries

FCompressedBuffer

? * N

 

Footer

FPackageTrailer::FFooter

20

 

标签:Engine,Int32,5.2,void,文件格式,FName,cpp,区块,TArray
From: https://www.cnblogs.com/bodong/p/17618007.html

相关文章

  • 让Photoshop支持.ICO文件格式
    需要安装一个文件插件ICOFormat.8bi。官方下载地址:http://www.telegraphics.net/sw/下载以后的存放路径:...\Required\Plug-ins\FileFormats参考网址:https://blog.csdn.net/weixin_44222492/article/details/101596183......
  • 在使用时序数据库 TDengine 进行 SQL 查询时,这些问题需要注意
    小T导读:尽管时序数据处理的特点是以写操作为主,读操作为辅,但查询需求也不容忽视。为方便用户上手,时序数据库(TimeSeriesDatabase)TDengine 采用SQL作为查询语言,主要查询功能包括单列及多列数据查询、数值列及聚合结果的四则运算、时间戳对齐的连接查询操作等,本文将就部分查询......
  • springboot集成seata1.5.2+nacos2.1.1
    一、前言Seata出现前,大部分公司使用的都是TCC或者MQ(RocketMq)等来解决分布式事务的问题,TCC代码编写复杂,每个业务均需要实现三个入口,侵入性强,RocketMQ保证的是最终一致性。二、环境准备1、nacos:(这里采用最新版本2.1.1)下载地址:https://github.com/alibaba/nacos/releases......
  • 实力认证!TDengine 入选 Gartner 中国数据分析与人工智能技术成熟度曲线
    近日,国际权威研究机构Gartner发布了《2023年中国数据分析及人工智能技术成熟度曲线》(即《HypeCycleforData,AnalyticsandAIinChina,2023》)报告,TDengine成功入选实时数据管理领域代表产品。作为评估全球新技术成熟度发展阶段的权威评价体系,GartnerHypeCycle公示的......
  • .NET ORM 鉴别器 和 TDengine 使用 -SqlSugar
    SqlSugarORMSqlSugar是一款老牌.NET开源多库架构ORM框架,一套代码能支持多种数据库像Admin.net、Blog.Core、CoreShop等知名开源项目都采用了SqlSugar作为底层特色1:超级简单在不用任何设计模式,任何框架的情况下都可以拥有最佳体验,SqlSugar做到了保姆一样的服务,直接用不需......
  • 【闲话】08.05.23
    08.05闲话众所周知,一个鲜花需要一张头图推歌:flower&CASI《藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁藁......
  • 一键获取测试脚本,轻松验证 TDengine 3.0 IoT 场景下 TSBS 测试报告
    不久前,基于TSBS,我们发布了TDengine3.0测试报告系列第一期——《DevOps场景下TDengine3.0对比测试报告》,报告验证了TDengine基于时序数据场景所设计的独特架构,在DevOps场景下带来的性能优势以及成本控制水平。本期我们继续探寻在IoT场景下,TDengine对比TimescaleDB、......
  • TDengine vs InfluxDB:写入速度领先 16.2 倍,查询速度超百倍
    为了验证TDengine3.0在IoT场景下的性能,我们针对第三方基准性能测试平台TSBS(TimeSeriesBenchmarkSuite)中的IoT场景,预设了五种规模的卡车车队基础数据集,在相同的AWS云环境下对TDengine3.0和InfluxDB1.8(该版本是InfluxDB能够运行TSBS框架的最新版本)进行了对比......
  • 大规模异常滥用检测:基于局部敏感哈希算法——来自Uber Engineering的实践
     uber全球用户每天会产生500万条行程,保证数据的准确性至关重要。如果所有的数据都得到有效利用,t通过元数据和聚合的数据可以快速检测平台上的滥用行为,如垃圾邮件、虚假账户和付款欺诈等。放大正确的数据信号能使检测更精确,也因此更可靠。为了解决我们和其他系统中的类似挑战,UberE......
  • InnoDB – the best storage engine for MySQL?
    https://dev.mysql.com/doc/refman/5.7/en/innodb-introduction.html InnoDBisageneral-purposestorageenginethatbalanceshighreliabilityandhighperformance.InnoDB是一个通用的存储引擎,平衡了高可靠性和高性能。InMySQL5.7,InnoDBisthedefaultMySQLsto......