Skip to content

Commit 9eee524

Browse files
Parse and expose ScriptType table
Final step of fully parsing the metadata section of serialized files
1 parent 7982401 commit 9eee524

4 files changed

Lines changed: 59 additions & 7 deletions

File tree

Analyzer.Tests/FileDetectionTests.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,16 @@ public void TryParseMetadata_V22PrefabWithSerializedReference_ReturnsExpectedTyp
364364
Assert.That(monoBehaviour.TypeDependencies[0], Is.EqualTo(0),
365365
"MonoBehaviour should record dependency on SerializedReference");
366366

367+
// --- Script types ---
368+
// ScriptTypeIndex=0 on the MonoBehaviour entry above means it is backed by ScriptTypes[0].
369+
// The MonoScript lives in external file #1 (the companion monoscriptbundle).
370+
Assert.IsNotNull(metadata.ScriptTypes, "ScriptTypes should be populated");
371+
Assert.That(metadata.ScriptTypes.Length, Is.EqualTo(1), "Should have 1 script type entry");
372+
Assert.That(metadata.ScriptTypes[0].FileID, Is.EqualTo(1),
373+
"ScriptTypes[0].FileID should be 1 (first external reference)");
374+
Assert.That(metadata.ScriptTypes[0].PathID, Is.EqualTo(3225487681952536265L),
375+
"ScriptTypes[0].PathID should match the MonoScript object ID in monoscriptbundle");
376+
367377
// --- SerializedReference type entry ---
368378
Assert.That(metadata.SerializedReferenceTypeTrees.Length, Is.EqualTo(1));
369379
var refType = metadata.SerializedReferenceTypeTrees[0];

Analyzer/Util/SerializedFileDetector.cs

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,24 @@ public class TypeTreeInfo
138138
public int[] TypeDependencies { get; set; } = Array.Empty<int>();
139139
}
140140

141+
/// <summary>
142+
/// A reference to a MonoScript object that backs a C# MonoBehaviour type recorded in this file.
143+
/// Corresponds to one entry in the file's m_ScriptTypes list.
144+
/// </summary>
145+
public class ScriptType
146+
{
147+
/// <summary>
148+
/// Index into the file's external references list, identifying which SerializedFile contains
149+
/// the MonoScript object. 0 = this file itself; 1+ = 1-based index into the externals list.
150+
/// </summary>
151+
public int FileID { get; set; }
152+
153+
/// <summary>
154+
/// The object ID (localIdentifierInFile) of the MonoScript within the identified file.
155+
/// </summary>
156+
public long PathID { get; set; }
157+
}
158+
141159
/// <summary>
142160
/// Information extracted from the beginning of a Unity SerializedFile metadata section.
143161
/// </summary>
@@ -170,6 +188,14 @@ public class SerializedFileMetadata
170188
/// </summary>
171189
public TypeTreeInfo[] SerializedReferenceTypeTrees { get; set; }
172190

191+
/// <summary>
192+
/// List of MonoScript references for the C# types used in this file.
193+
/// Each entry points to the MonoScript object (in this file or an external file) that backs
194+
/// a C# MonoBehaviour-derived type whose ScriptTypeIndex is the index of that entry here.
195+
/// Null until the metadata section has been parsed.
196+
/// </summary>
197+
public ScriptType[] ScriptTypes { get; set; }
198+
173199
/// <summary>
174200
/// List of all objects recorded in the file's object table.
175201
/// Null until the metadata section has been parsed.
@@ -612,18 +638,22 @@ private static void ParseExtendedMetadata(BinaryReader reader, SerializedFileInf
612638
}
613639
metadata.ObjectList = objectList;
614640

615-
// --- Skip the script type list ---
641+
// --- Script type list ---
642+
// Each entry points to the MonoScript object that backs a C# MonoBehaviour-derived type.
616643
// Per-entry layout (version >= 14, applies to all our versions):
617-
// [int32 localSerializedFileIndex]
644+
// [int32 localSerializedFileIndex] (FileID: 0 = this file, 1+ = external ref index)
618645
// [4-byte alignment relative to metadata start]
619-
// [int64 localIdentifierInFile]
646+
// [int64 localIdentifierInFile] (PathID: object ID within the identified file)
620647
int scriptTypeCount = BinaryFileHelper.ReadInt32(reader, swap);
648+
var scriptTypes = new ScriptType[scriptTypeCount];
621649
for (int i = 0; i < scriptTypeCount; i++)
622650
{
623-
stream.Seek(4, SeekOrigin.Current); // int32 localSerializedFileIndex
651+
int fileID = BinaryFileHelper.ReadInt32(reader, swap);
624652
BinaryFileHelper.AlignTo4(stream, metadataOffset);
625-
stream.Seek(8, SeekOrigin.Current); // int64 localIdentifierInFile
653+
long pathID = BinaryFileHelper.ReadInt64(reader, swap);
654+
scriptTypes[i] = new ScriptType { FileID = fileID, PathID = pathID };
626655
}
656+
metadata.ScriptTypes = scriptTypes;
627657

628658
// --- External references list ---
629659
// Per-entry layout:

Documentation/command-serialized-file.md

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -253,11 +253,12 @@ UnityDataTool serialized-file metadata level0 --format json
253253
"typeTreeCount": 6,
254254
"serializedReferenceTypeTreeCount": 0,
255255
"typeTrees": [ ... ],
256-
"serializedReferenceTypeTrees": [ ... ]
256+
"serializedReferenceTypeTrees": [ ... ],
257+
"scriptTypes": [ ... ]
257258
}
258259
```
259260

260-
Each element of `typeTrees` and `serializedReferenceTypeTrees` contains per-type details including hash values, TypeTree blob size, inline/external flag, and (for SerializeReference types) the C# class identity.
261+
Each element of `typeTrees` and `serializedReferenceTypeTrees` contains per-type details including hash values, TypeTree blob size, inline/external flag, and (for SerializeReference types) the C# class identity. Each element of `scriptTypes` contains the file and object ID of the backing MonoScript asset.
261262

262263
### Metadata Fields
263264

@@ -272,6 +273,7 @@ The text and JSON outputs use different field names and representations for some
272273
| **RefType Count** | `serializedReferenceTypeTreeCount` | Number of type entries for `[SerializeReference]` types recorded in the file. Always `0` for files with version < 20. |
273274
| *(JSON only)* | `typeTrees` | Array of per-type detail objects for the regular type entries. `null` when parsing failed or was not attempted. See **Per-Type Entry Fields** below. |
274275
| *(JSON only)* | `serializedReferenceTypeTrees` | Array of per-type detail objects for the `[SerializeReference]` type entries. Empty array for files with version < 20. See **Per-Type Entry Fields** below. |
276+
| *(JSON only)* | `scriptTypes` | Array of MonoScript references for the C# types used in this file. Each entry's index corresponds to the `scriptTypeIndex` field of a type entry in `typeTrees`. See **Script Type Entry Fields** below. |
275277

276278
### Per-Type Entry Fields
277279

@@ -292,6 +294,15 @@ Each element of `typeTrees` and `serializedReferenceTypeTrees` in the JSON outpu
292294
| `assemblyName` | Assembly name; non-empty only for `[SerializeReference]` entries (version ≥ 21). |
293295
| `typeDependencies` | Array of indices into `serializedReferenceTypeTrees` listing which `[SerializeReference]` types objects of this type may hold. Empty for `[SerializeReference]` entries or files with version < 21. |
294296

297+
### Script Type Entry Fields
298+
299+
Each element of `scriptTypes` in the JSON output contains:
300+
301+
| JSON Field | Description |
302+
|------------|-------------|
303+
| `fileID` | Index into the file's external references list identifying which SerializedFile contains the MonoScript asset. `0` = this file itself; `1`+ = 1-based index into the `externalrefs` list. |
304+
| `pathID` | The object ID (`localIdentifierInFile`) of the MonoScript within the identified file. Corresponds to the `id` field shown by `sf objectlist` on that file. |
305+
295306
Notes:
296307

297308
* For SerializedFiles inside AssetBundles the Unity Version is frequently stripped ("0.0.0"). See [BuildAssetBundleOptions.AssetBundleStripUnityVersion](https://docs.unity3d.com/ScriptReference/BuildAssetBundleOptions.AssetBundleStripUnityVersion.html).

UnityDataTool/SerializedFileCommands.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,7 @@ private static void OutputMetadataJson(SerializedFileMetadata metadata)
271271
serializedReferenceTypeTreeCount = metadata.SerializedReferenceTypeTreeCount,
272272
typeTrees = metadata.TypeTrees?.Select(TypeTreeInfoToJson).ToArray(),
273273
serializedReferenceTypeTrees = metadata.SerializedReferenceTypeTrees?.Select(TypeTreeInfoToJson).ToArray(),
274+
scriptTypes = metadata.ScriptTypes?.Select(s => new { fileID = s.FileID, pathID = s.PathID }).ToArray(),
274275
};
275276

276277
var json = JsonSerializer.Serialize(jsonObject, new JsonSerializerOptions { WriteIndented = true });

0 commit comments

Comments
 (0)