Skip to content

SerializedFile containers

A Unity player keeps its scenes and assets in SerializedFiles: one container format for globalgamemanagers, globalgamemanagers.assets, resources.assets, every levelN (a scene) and every sharedassetsN.assets (the assets scenes share). A file is a header, a block of metadata (which types occur, where each object’s bytes are, which other files it points into) and the objects’ bytes. Bulk data (texture pixels, vertex streams, audio) is not inside: objects name a range of a .resS or .resource file beside it. Proven · SkateBIRD

Three container versions occur in the games here. Enter the Gungeon (Unity 2017.4) writes version 17; SkateBIRD (Unity 2019.4) writes version 21; Risk of Rain 2 (2021.3), Schedule I (2022.3), Sledding Game, PEAK and Big Walk (Unity 6000.3) write version 22. Proven · every serialized file of each install The same containers sit inside a UnityFS bundle when a build packs its data into one; Big Walk does.

Game Container Unity version in the file Files Embedded type trees Confidence
Enter the Gungeon 17 2017.4.27f1 5 none Proven
Enter the Gungeon’s bundles 17 2017.4.27f1 34 (inside 30 bundles) every type Proven
SkateBIRD 21 2019.4.20f1 31 none Proven
Risk of Rain 2 22 2021.3.45f2 5 none Proven
Schedule I 22 2022.3.62f2 9 none Proven
Sledding Game 22 6000.3.12f1 7 none Proven
PEAK 3.0.0 22 6000.3.15f1 13 none Proven
Big Walk 22 6000.3.17f1 12 (inside data.unity3d) none Proven
Sledding Game’s Addressables 22 6000.3.12f1 50 (inside 50 bundles) every type Proven
PEAK 3.0.0’s level bundles 22 6000.3.15f1 417 (inside 8 bundles) every type of 416 files, none in the manifest bundle maps Proven

“Proven” here is a census of every serialized file of the install: each header parses, the stated file size equals the file’s size, the data offset is a multiple of 16 and lies after the metadata, the target platform is 19 (Windows x64), and the has-type-tree byte is 0. Player builds strip type trees from their files; the layout of each class is supplied from outside (type trees). The files in bundles are the other case: the same census of the 479 serialized files of the three games’ bundles (a second reader agrees on every header, type, object table and external) finds the has-type-tree byte 1 in 466 of them, where each type is followed by its tree.

The header’s first fields are big-endian whatever the file’s endianness byte says; the metadata after it is read in the file’s own endianness (little in every file measured). Proven

SerializedFile header, version 2120 bytesSkateBIRD100% known

All fields big-endian. The metadata starts at byte 20 and ends metadata size bytes later; object bytes start at the data offset.

ProvenObservedSourcedInferredUnknownNot described
OffsetSizeTypeFieldConfidenceNotes
0x04u32metadata sizeProvenbytes of metadata after the header; 1,340 in SkateBIRD's globalgamemanagers
0x44u32file sizeProvenequals the file's length in every file
0x84u32 = 21versionProven
0xC4u32data offsetProvenwhere the objects' bytes begin; a multiple of 16 in every file (4,096 in globalgamemanagers)
0x101u8endiannessProven0 little-endian in every file
0x113u8[3]reservedProvenzero

Version 22 keeps the version-21 field positions for the version but zeroes the old size fields and repeats them wider after the endianness bytes: sizes and the data offset become 32-, 64- and 64-bit numbers. Proven · Sledding, PEAK, Big Walk

SerializedFile header, version 2248 bytesSleddingPEAKBig Walk100% known

All fields big-endian. The metadata starts at byte 48.

ProvenObservedSourcedInferredUnknownNot described
OffsetSizeTypeFieldConfidenceNotes
0x04u32 = 0legacy metadata sizeProvenunused in version 22
0x44u32 = 0legacy file sizeProvenunused in version 22
0x84u32 = 22versionProven
0xC4u32 = 0legacy data offsetProvenunused in version 22
0x101u8endiannessProven0 little-endian in every file
0x113u8[3]reservedProvenzero
0x144u32metadata sizeProven
0x188u64file sizeProvenequals the file's length in every file
0x208u64data offsetProvena multiple of 16 in every file
0x288u64 = 0reservedProvenzero in every file

The metadata follows the header in this order. Counts are i32. Proven · SkateBIRD The reader that parses this order consumes the metadata of every SkateBIRD file to its stated end, and its object tables match an independent reader’s on all 503,045 objects of the 31 files (path ids, class ids, byte offsets and sizes). Proven · SkateBIRD

Part Content Confidence
Unity version NUL-terminated string (2019.4.20f1) Proven
Target platform i32; 19 in every file Proven
Has type trees u8; 0 in every file (stripped) Proven
Types count, then one type entry each Proven
Objects count, then one object entry each Proven
Script types count, then per entry a file index (i32), 4-byte alignment, a path id (i64) Proven · SkateBIRD
External files count, then per entry an empty string, a 16-byte GUID, a kind (i32) and a path string Proven · SkateBIRD
Reference types count, then type entries with a script id when the script index is not negative; with stored trees each is followed by its tree and three strings Proven · PEAK, Sledding, Big Walk
User information NUL-terminated string Proven · SkateBIRD
Type entryvariable100% known

23 bytes for a class other than MonoBehaviour (114), 39 for MonoBehaviour. In the metadata endianness (little).

ProvenObservedSourcedInferredUnknownNot described
OffsetSizeTypeFieldConfidenceNotes
0x04i32class idProvenUnity's class id (1 GameObject, 4 Transform, 21 Material, 28 Texture2D, 43 Mesh, 114 MonoBehaviour, ...)
0x41u8strippedProven
0x52i16script type indexProven-1 for a class other than MonoBehaviour
0x716u8[16]script idProvenonly present when the class id is 114 (MonoBehaviour): the hash of the script's identity
7, or 23 with a script id16u8[16]old type hashSourcedUnityPy's name; the hash of the class's layout

When the has-type-tree byte is 1, each type entry (and each reference type entry) continues after its old type hash with the type’s tree, then, for an ordinary type, a list of type indices, and for a reference type three strings. Proven · PEAK, Sledding The metadata of all 466 files that store trees is consumed exactly to its stated end by this layout, and an independent reader gives the same tree for every one of the 83,867 types. Proven · PEAK, Sledding

Stored type tree (after the old type hash)variablePEAKSledding100% known

In the metadata endianness (little). Nodes are in depth-first order; a node's parent is the nearest earlier node whose level is one less.

ProvenObservedSourcedInferredUnknownNot described
OffsetSizeTypeFieldConfidenceNotes
0x04i32node countProvenat least 1
0x44i32string buffer sizeProven
0x832 per nodenode[]nodesProvensee the node layout
after the nodesstring buffer sizechar[]string bufferProvenNUL-terminated strings
after the buffervariablei32 count + i32[]type dependenciesProvenordinary types: indices into the type table (empty for most)
after the buffervariablechar[] x3class, namespace and assemblyProvenreference types instead of the dependency list: three NUL-terminated strings
Stored type tree node32 bytesPEAKSledding100% known

In the metadata endianness (little).

ProvenObservedSourcedInferredUnknownNot described
OffsetSizeTypeFieldConfidenceNotes
0x02i16versionProventhe node's version, as in a package's tree
0x21u8levelProven0 for the root, a child's level is its parent's plus one
0x31u8type flagsObserved0, or 1 on Array and TypelessData nodes, 2 on managedReference nodes, 4 on ManagedReferencesRegistry, 8 on the element type of an array of managed references: values 0, 1, 2, 4 and 8 in 180,511 nodes of 13 files
0x44u32type string offsetProventop bit clear: offset into the string buffer; top bit set: the low 31 bits are an offset into the engine's common string table
0x84u32name string offsetProvenas the type string offset
0xC4i32byte sizeProven-1 where the size varies
0x104i32indexObservedthe node's position in the list, in all 180,511 nodes of 13 files
0x144u32meta flagsProven0x4000 aligns the position to 4 bytes after the node
0x188u64reference type hashObserved0 in all 180,511 nodes of 13 files

Each entry starts on a 4-byte boundary of the file. The object’s bytes are size bytes at data offset + start; its class is that of its type entry. Path ids are unique within a file. Proven

Object entry, version 2120 bytesSkateBIRD100% known
ProvenObservedSourcedInferredUnknownNot described
OffsetSizeTypeFieldConfidenceNotes
0x08i64path idProventhe object's identity within this file
0x84u32startProvenoffset from the data offset
0xC4u32sizeProven
0x104u32type indexProvenindex into the type table
Object entry, version 2224 bytesSleddingPEAKBig Walk100% known

As version 21 but the start is 64 bits wide.

ProvenObservedSourcedInferredUnknownNot described
OffsetSizeTypeFieldConfidenceNotes
0x08i64path idProven
0x88i64startProven
0x104u32sizeProven
0x144u32type indexProven

An object points at another with a PPtr: a file id and a path id. File id 0 is the same file; file id n is external file n − 1 of the metadata. Sourced · UnityPy A script field that stores an object reference writes it as 12 bytes: an i32 file id and an i64 path id, a path id of 0 meaning null. Observed · SkateBIRD, Sledding

Scenes link the shared libraries through their externals. SkateBIRD’s level12 lists globalgamemanagers.assets, sharedassets0 to sharedassets5, sharedassets7, sharedassets12, resources.assets and Library/unity default resources; level13 adds sharedassets13. Observed · SkateBIRD A scene file holds no Texture2D, Material, Shader or AudioClip object in any of SkateBIRD’s 14 scenes; its renderers reference the sharedassets files. Observed · SkateBIRD

A field marked [SerializeReference] stores a reference to a plain C# object, not a Unity object. An object that has such fields ends with a ManagedReferencesRegistry named references: an int version and a vector RefIds of ReferencedObjects, each an SInt64 rid, a ReferencedManagedType type (three strings: class, ns, asm) and a ReferencedObjectData data. The fields that hold a reference store its rid. The data is laid out by the tree of the class type names, which the file keeps in its reference types (matched by class, namespace and assembly), not in the object’s own tree; a null reference has an empty class and no data. Sourced · UnityPy All 1,427 objects of Sledding Game’s 50 bundles decode by that rule, each to exactly its last byte, the 94 MonoBehaviours with [SerializeReference] fields among them. Proven · Sledding A referenced object’s own tree names a registry of its own, which is not stored: those objects decode to their last byte with it left out. Proven · Sledding

A reader accepts a container version it was checked against and refuses others: versions 17, 21 and 22 are the ones verified against real data here. Observed A version 21 file is not a version 22 file read with other widths; field offsets and the object table differ, so one reader needs both layouts. Proven

Version 17 has the version 21 header and object entry. Its metadata differs in three ways: a stored tree node is 24 bytes (no reference type hash, at 24 in later versions), there is no reference types table, and a type has no dependency list. Proven · Gungeon Enter the Gungeon’s 5 loose files read so with the object table an independent reader gives (4,285 objects), and every one of the 93,034 objects of its 30 bundles’ 34 files decodes by its stored tree to exactly its last byte. Proven · Gungeon The reference type hash arrives in version 19, the reference types table in version 20 and the dependency lists (and a reference type’s class names) in version 21. Sourced · UnityPy, AssetStudio

Containers 18 to 20, and older or newer than 17 to 22

No game documented here writes 18, 19 or 20, so where their fields begin rests on two readers’ sources. Unity’s serialized container has older versions too (older players), and newer editors may raise it. What would settle 18 to 20: one player of Unity 2018.x or 2019.1 to 2019.2 read with an independent reader.

Sources

  • UnityPy — SerializedFile reader; the field order of the metadata
  • AssetRipper — documents the container versions and publishes the type tree package (TPK)
  • AssetStudio — SerializedFile reader; the versions at which the metadata gains fields

Implementations