From 3308843e34de7cd3176b7ec8e007cbfacabfa55c Mon Sep 17 00:00:00 2001 From: Andrew Skowronski Date: Mon, 6 Jul 2026 11:14:27 -0400 Subject: [PATCH 1/4] More documentation of the project structure in main README --- README.md | 89 ++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 71 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 2a052ef..87fd922 100644 --- a/README.md +++ b/README.md @@ -37,19 +37,76 @@ New to Unity's data files or to UnityDataTool? These topics are a good place to ## Repository content -The repository contains the following items: -* [UnityDataTool](Documentation/unitydatatool.md): a command-line tool providing access to the Analyzer, TextDumper and other class libraries. -* [Analyzer](Documentation/analyzer.md): a class library that can be used to extract key information - from Unity data files and output it into a SQLite database. -* [TextDumper](Documentation/textdumper.md): a class library that can be used to dump SerializedFiles into - a human-readable format (similar to binary2text). -* [ReferenceFinder](Documentation/referencefinder.md): a class library that can be used to find - reference chains from objects to other objects using a database created by the Analyzer -* UnityFileSystem: source code and binaries of a .NET class library exposing the functionalities or the - UnityFileSystemApi native library. -* UnityFileSystem.Tests: test suite for the UnityFileSystem library. -* UnityProjects: Unity projects used to generate some of the test data. -* TestCommon: a helper library used by the test projects. +The solution is organised in three layers. At the base are the libraries that read Unity's binary +formats. On top of those sit the feature libraries that turn that raw data into something useful +(a database, a text dump, a reference graph). And at the top is the command-line tool that exposes +all of that functionality to users. + +```mermaid +flowchart TD + CLI["UnityDataTool
command-line tool
(+ archive / serialized-file commands)"] + + Analyzer["Analyzer
SQLite database"] + TextDumper["TextDumper
human-readable dump"] + ReferenceFinder["ReferenceFinder
reference chains"] + + UnityFileSystem["UnityFileSystem
C# wrapper +
UnityFileSystemApi (native)"] + UnityBinaryFormat["UnityBinaryFormat
C# parsers & helpers
for Archives / SerializedFiles"] + UnityDataModels["UnityDataModels
schemas for build reporting file formats"] + + CLI --> Analyzer + CLI --> TextDumper + CLI --> ReferenceFinder + CLI --> UnityBinaryFormat + CLI --> UnityFileSystem + + Analyzer --> UnityFileSystem + Analyzer --> UnityBinaryFormat + Analyzer --> UnityDataModels + TextDumper --> UnityFileSystem + TextDumper --> UnityBinaryFormat + UnityBinaryFormat --> UnityFileSystem + + ReferenceFinder -. "reads the SQLite database" .-> Analyzer +``` + +**Command-line tool** +* [UnityDataTool](Documentation/unitydatatool.md): the command-line tool. It wires the feature + libraries together and exposes them as commands (`analyze`, `dump`, `find-refs`, and more), so most + users only ever interact with this executable. It also directly contains the implementation of the + `archive` and `serialized-file` commands — critical features for working with the file formats, + built mostly on top of UnityBinaryFormat. + +**Feature libraries** +* [Analyzer](Documentation/analyzer.md): extracts key information from Unity data files into a SQLite + database for detailed analysis. It also parses Addressables build reports. +* [TextDumper](Documentation/textdumper.md): dumps SerializedFiles into a human-readable format + (similar to Unity's binary2text). +* [ReferenceFinder](Documentation/referencefinder.md): finds reference chains from one object to + another by querying a database produced by the Analyzer (a data dependency rather than a code one). + +**Base libraries** +* UnityFileSystem: a .NET class library, with source and binaries, that wraps the native + `UnityFileSystemApi` to mount Unity Archives and read SerializedFiles. +* UnityBinaryFormat: C# parsers and helpers for reading data out of Unity Archives and SerializedFiles. +* UnityDataModels: shared C# models for the reading JSON format files produced by the build (Addressables BuildLayout.json, Content Directory ContentLayout.json). + +## Purpose of UnityFileSystemApi + +UnityFileSystemApi is compiled from the Unity source code and exposes the core functionality to open and read the Unity Archive and Serialized File formats, exposed as a flexible, performant library. It exposes ability to navigates the TypeTrees inside a SerializedFile so objects can be read generically, without hardcoded type knowledge. + +It enables custom tools for binary2text-like output and efficient SQLite database generation. + +### Tests and test data + +The automated tests are not shown in the diagram above. Each library has its own test project, and the +shared test data doubles as convenient sample content for ad hoc use of the tool. + +* TestCommon: a helper library whose `Data/` folder holds small reference files extracted from real + Unity builds (Player, AssetBundles, content directory etc). These back the automated tests and are also handy for trying out the tool by hand. +* Analyzer.Tests, UnityDataTool.Tests, UnityFileSystem.Tests: the per-library test suites. +* UnityProjects: two Unity projects (`Baseline` and `LeadingEdge`) used to regenerate some of the test + data as Unity evolves. ## Downloads @@ -63,7 +120,7 @@ Refer to the [commit history](https://github.com/Unity-Technologies/UnityDataToo ## Getting UnityFileSystemApi -UnityDataTool uses the native `UnityFileSystemApi` library to read Unity Archives and SerializedFiles. **Normally you don't need to do anything with this library.** The repository already includes a recent Windows, Mac, and Linux copy in the [`UnityFileSystem/`](https://github.com/Unity-Technologies/UnityDataTools/tree/main/UnityFileSystem) directory, and using that bundled copy is the recommended way to run the tool. +UnityDataTool uses the pre-compiled `UnityFileSystemApi` library to read Unity Archives and SerializedFiles. **Normally you don't need to do anything with this library.** The repository already includes a recent Windows, Mac, and Linux copy in the [`UnityFileSystem/`](https://github.com/Unity-Technologies/UnityDataTools/tree/main/UnityFileSystem) directory, and using that bundled copy is the recommended way to run the tool. The library is backward compatible but not forward compatible: a given version can read content from the same or older Unity versions, but may be unable to read content produced by a newer Unity Editor than the library itself. The bundled copy is updated periodically as Unity evolves, so in practice it can read content from just about any Unity version. @@ -84,10 +141,6 @@ On Windows, the executable is written to `UnityDataTool\bin\Release\net9.0`. Add See the [command-line tool documentation](./Documentation/unitydatatool.md) for usage instructions. -## Purpose of UnityFileSystemApi - -UnityFileSystemApi exposes the core functionality of WebExtract and binary2text to open and read the Unity Archive and Serialized File formats, exposed as a flexible, performant library. It enables custom tools for binary2text-like output and efficient SQLite database generation. - ## Origins This tool is the evolution of the [AssetBundle Analyzer](https://github.com/faelenor/asset-bundle-analyzer) From bb53df12fcad87590697f835f05f82c65b97d688 Mon Sep 17 00:00:00 2001 From: Andrew Skowronski Date: Mon, 6 Jul 2026 12:48:38 -0400 Subject: [PATCH 2/4] Restructure Archive and SerializedFile code into their own libraries For consistency with the other command implementations - it didn't make much sense that some commands were implemented directly inside UnityDataTool and others as separate libraries. --- AGENTS.md | 16 +++++++--- Archive/Archive.csproj | 28 +++++++++++++++++ .../Archive.cs => Archive/ArchiveTool.cs | 10 +++++-- Archive/README.md | 3 ++ {UnityDataTool => Archive}/WebBundleHelper.cs | 6 ++-- README.md | 22 +++++++++----- SerializedFile/README.md | 3 ++ SerializedFile/SerializedFile.csproj | 24 +++++++++++++++ .../SerializedFileTool.cs | 10 +++++-- UnityDataTool.Tests/WebBundleSupportTests.cs | 1 + UnityDataTool/Program.cs | 30 ++++++++----------- UnityDataTool/UnityDataTool.csproj | 6 ++-- UnityDataTools.sln | 28 +++++++++++++++++ 13 files changed, 149 insertions(+), 38 deletions(-) create mode 100644 Archive/Archive.csproj rename UnityDataTool/Archive.cs => Archive/ArchiveTool.cs (99%) create mode 100644 Archive/README.md rename {UnityDataTool => Archive}/WebBundleHelper.cs (96%) create mode 100644 SerializedFile/README.md create mode 100644 SerializedFile/SerializedFile.csproj rename UnityDataTool/SerializedFileCommands.cs => SerializedFile/SerializedFileTool.cs (98%) diff --git a/AGENTS.md b/AGENTS.md index ac51699..ce6e852 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -90,14 +90,22 @@ UnityDataTool find-refs database.db -n "ObjectName" -t "Texture2D" ### Component Hierarchy ``` -UnityDataTool (CLI executable) +UnityDataTool (CLI executable) — wires the feature libraries into commands ├── Analyzer → SQLite database generation ├── TextDumper → Human-readable text output -├── ReferenceFinder → Object reference chain tracing -└── UnityFileSystem → C# wrapper for native library - └── UnityFileSystemApi (native .dll/.dylib/.so) +├── ReferenceFinder → Object reference chain tracing (queries the Analyzer database) +├── Archive → inspect / extract Unity Archives (the `archive` command) +├── SerializedFile → inspect SerializedFile header/metadata/objects (the `serialized-file` command) +└── (base libraries, used by the feature libraries above) + ├── UnityBinaryFormat → C# parsers & helpers for Archives / SerializedFiles + ├── UnityDataModels → schemas for JSON build-report formats + └── UnityFileSystem → C# wrapper for native library + └── UnityFileSystemApi (native .dll/.dylib/.so) ``` +The feature libraries each build on UnityBinaryFormat and UnityFileSystem. See the +"Repository content" section of `README.md` for a diagram of the dependencies. + ### Key Architectural Patterns **Native Interop**: UnityFileSystem wraps UnityFileSystemApi (native library from Unity Editor) via P/Invoke in `DllWrapper.cs`. The native library reads Unity Archive and SerializedFile formats. diff --git a/Archive/Archive.csproj b/Archive/Archive.csproj new file mode 100644 index 0000000..bc5a88c --- /dev/null +++ b/Archive/Archive.csproj @@ -0,0 +1,28 @@ + + + + Library + net9.0 + + + latest + + + + AnyCPU + + + + AnyCPU + + + + + + + + + + + + diff --git a/UnityDataTool/Archive.cs b/Archive/ArchiveTool.cs similarity index 99% rename from UnityDataTool/Archive.cs rename to Archive/ArchiveTool.cs index b997379..517b74b 100644 --- a/UnityDataTool/Archive.cs +++ b/Archive/ArchiveTool.cs @@ -5,10 +5,16 @@ using UnityDataTools.BinaryFormat; using UnityDataTools.FileSystem; -namespace UnityDataTools.UnityDataTool; +namespace UnityDataTools.Archive; -public static class Archive +public static class ArchiveTool { + public enum OutputFormat + { + Text, + Json + } + public static int HandleExtract(FileInfo filename, DirectoryInfo outputFolder, string filter = null) { try diff --git a/Archive/README.md b/Archive/README.md new file mode 100644 index 0000000..4f87ea4 --- /dev/null +++ b/Archive/README.md @@ -0,0 +1,3 @@ +# Archive + +See [Documentation/command-archive.md](../Documentation/command-archive.md) diff --git a/UnityDataTool/WebBundleHelper.cs b/Archive/WebBundleHelper.cs similarity index 96% rename from UnityDataTool/WebBundleHelper.cs rename to Archive/WebBundleHelper.cs index 4403b30..3e91dd8 100644 --- a/UnityDataTool/WebBundleHelper.cs +++ b/Archive/WebBundleHelper.cs @@ -6,7 +6,7 @@ using System.Text; using System.Text.Json; -namespace UnityDataTools.UnityDataTool; +namespace UnityDataTools.Archive; public static class WebBundleHelper { @@ -50,14 +50,14 @@ public static void Extract(FileInfo filename, DirectoryInfo outputFolder, string Console.WriteLine($"Extracted {extracted} out of {total} files."); } - public static void List(FileInfo filename, OutputFormat format) + public static void List(FileInfo filename, ArchiveTool.OutputFormat format) { using var fileStream = File.Open(filename.ToString(), FileMode.Open); using var stream = GetStream(filename, fileStream); using var reader = new BinaryReader(stream, Encoding.UTF8); var fileDescriptions = ParseWebBundleHeader(reader); - if (format == OutputFormat.Json) + if (format == ArchiveTool.OutputFormat.Json) { var jsonArray = new object[fileDescriptions.Count]; for (int i = 0; i < fileDescriptions.Count; i++) diff --git a/README.md b/README.md index 87fd922..694ab90 100644 --- a/README.md +++ b/README.md @@ -44,11 +44,13 @@ all of that functionality to users. ```mermaid flowchart TD - CLI["UnityDataTool
command-line tool
(+ archive / serialized-file commands)"] + CLI["UnityDataTool
command-line tool"] Analyzer["Analyzer
SQLite database"] TextDumper["TextDumper
human-readable dump"] ReferenceFinder["ReferenceFinder
reference chains"] + Archive["Archive
inspect / extract archives"] + SerializedFile["SerializedFile
inspect SerializedFiles"] UnityFileSystem["UnityFileSystem
C# wrapper +
UnityFileSystemApi (native)"] UnityBinaryFormat["UnityBinaryFormat
C# parsers & helpers
for Archives / SerializedFiles"] @@ -57,14 +59,18 @@ flowchart TD CLI --> Analyzer CLI --> TextDumper CLI --> ReferenceFinder - CLI --> UnityBinaryFormat - CLI --> UnityFileSystem + CLI --> Archive + CLI --> SerializedFile Analyzer --> UnityFileSystem Analyzer --> UnityBinaryFormat Analyzer --> UnityDataModels TextDumper --> UnityFileSystem TextDumper --> UnityBinaryFormat + Archive --> UnityFileSystem + Archive --> UnityBinaryFormat + SerializedFile --> UnityFileSystem + SerializedFile --> UnityBinaryFormat UnityBinaryFormat --> UnityFileSystem ReferenceFinder -. "reads the SQLite database" .-> Analyzer @@ -72,10 +78,8 @@ flowchart TD **Command-line tool** * [UnityDataTool](Documentation/unitydatatool.md): the command-line tool. It wires the feature - libraries together and exposes them as commands (`analyze`, `dump`, `find-refs`, and more), so most - users only ever interact with this executable. It also directly contains the implementation of the - `archive` and `serialized-file` commands — critical features for working with the file formats, - built mostly on top of UnityBinaryFormat. + libraries together and exposes them as commands (`analyze`, `dump`, `find-refs`, `archive`, + `serialized-file`, and more), so most users only ever interact with this executable. **Feature libraries** * [Analyzer](Documentation/analyzer.md): extracts key information from Unity data files into a SQLite @@ -84,6 +88,10 @@ flowchart TD (similar to Unity's binary2text). * [ReferenceFinder](Documentation/referencefinder.md): finds reference chains from one object to another by querying a database produced by the Analyzer (a data dependency rather than a code one). +* [Archive](Documentation/command-archive.md): inspects and extracts the contents of Unity Archives + (AssetBundles and web platform `.data` files) — the `archive` command. +* [SerializedFile](Documentation/command-serialized-file.md): inspects the header, metadata, object + list, and external references of a SerializedFile — the `serialized-file` command. **Base libraries** * UnityFileSystem: a .NET class library, with source and binaries, that wraps the native diff --git a/SerializedFile/README.md b/SerializedFile/README.md new file mode 100644 index 0000000..a6d8bc6 --- /dev/null +++ b/SerializedFile/README.md @@ -0,0 +1,3 @@ +# SerializedFile + +See [Documentation/command-serialized-file.md](../Documentation/command-serialized-file.md) diff --git a/SerializedFile/SerializedFile.csproj b/SerializedFile/SerializedFile.csproj new file mode 100644 index 0000000..a5624d3 --- /dev/null +++ b/SerializedFile/SerializedFile.csproj @@ -0,0 +1,24 @@ + + + + Library + net9.0 + + + latest + + + + AnyCPU + + + + AnyCPU + + + + + + + + diff --git a/UnityDataTool/SerializedFileCommands.cs b/SerializedFile/SerializedFileTool.cs similarity index 98% rename from UnityDataTool/SerializedFileCommands.cs rename to SerializedFile/SerializedFileTool.cs index 3dd0dc3..c023546 100644 --- a/UnityDataTool/SerializedFileCommands.cs +++ b/SerializedFile/SerializedFileTool.cs @@ -5,10 +5,16 @@ using UnityDataTools.BinaryFormat; using UnityDataTools.FileSystem; -namespace UnityDataTools.UnityDataTool; +namespace UnityDataTools.SerializedFile; -public static class SerializedFileCommands +public static class SerializedFileTool { + public enum OutputFormat + { + Text, + Json + } + public static int HandleExternalRefs(FileInfo filename, OutputFormat format) { // External references are read directly from the parsed metadata rather than via UnityFileSystemApi. diff --git a/UnityDataTool.Tests/WebBundleSupportTests.cs b/UnityDataTool.Tests/WebBundleSupportTests.cs index 914f695..4d5db44 100644 --- a/UnityDataTool.Tests/WebBundleSupportTests.cs +++ b/UnityDataTool.Tests/WebBundleSupportTests.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Threading.Tasks; using NUnit.Framework; +using UnityDataTools.Archive; using UnityDataTools.FileSystem; namespace UnityDataTools.UnityDataTool.Tests; diff --git a/UnityDataTool/Program.cs b/UnityDataTool/Program.cs index c8e0794..1761955 100644 --- a/UnityDataTool/Program.cs +++ b/UnityDataTool/Program.cs @@ -5,18 +5,14 @@ using System.Reflection; using System.Threading.Tasks; using UnityDataTools.Analyzer; +using UnityDataTools.Archive; using UnityDataTools.FileSystem; using UnityDataTools.ReferenceFinder; +using UnityDataTools.SerializedFile; using UnityDataTools.TextDumper; namespace UnityDataTools.UnityDataTool; -public enum OutputFormat -{ - Text, - Json -} - public static class Program { const string TypeTreeDataDescription = "Path to an external TypeTree data file to load before processing bundles"; @@ -229,10 +225,10 @@ static Command BuildArchiveCommand() filterOpt, }; extractArchiveCommand.SetHandler( - (FileInfo fi, DirectoryInfo o, string filter) => Task.FromResult(Archive.HandleExtract(fi, o, filter)), + (FileInfo fi, DirectoryInfo o, string filter) => Task.FromResult(ArchiveTool.HandleExtract(fi, o, filter)), pathArg, oOpt, filterOpt); - var fOpt = new Option(aliases: new[] { "--format", "-f" }, description: "Output format", getDefaultValue: () => OutputFormat.Text); + var fOpt = new Option(aliases: new[] { "--format", "-f" }, description: "Output format", getDefaultValue: () => ArchiveTool.OutputFormat.Text); var listArchiveCommand = new Command("list", "List the contents of an AssetBundle or .data file.") { @@ -240,7 +236,7 @@ static Command BuildArchiveCommand() fOpt, }; listArchiveCommand.SetHandler( - (FileInfo fi, OutputFormat f) => Task.FromResult(Archive.HandleList(fi, f)), + (FileInfo fi, ArchiveTool.OutputFormat f) => Task.FromResult(ArchiveTool.HandleList(fi, f)), pathArg, fOpt); var headerArchiveCommand = new Command("header", "Display the header of a Unity Archive file.") @@ -249,7 +245,7 @@ static Command BuildArchiveCommand() fOpt, }; headerArchiveCommand.SetHandler( - (FileInfo fi, OutputFormat f) => Task.FromResult(Archive.HandleHeader(fi, f)), + (FileInfo fi, ArchiveTool.OutputFormat f) => Task.FromResult(ArchiveTool.HandleHeader(fi, f)), pathArg, fOpt); var blocksArchiveCommand = new Command("blocks", "Display the block list of a Unity Archive file.") @@ -258,7 +254,7 @@ static Command BuildArchiveCommand() fOpt, }; blocksArchiveCommand.SetHandler( - (FileInfo fi, OutputFormat f) => Task.FromResult(Archive.HandleBlocks(fi, f)), + (FileInfo fi, ArchiveTool.OutputFormat f) => Task.FromResult(ArchiveTool.HandleBlocks(fi, f)), pathArg, fOpt); var infoArchiveCommand = new Command("info", "Display a high-level summary of a Unity Archive file.") @@ -267,7 +263,7 @@ static Command BuildArchiveCommand() fOpt, }; infoArchiveCommand.SetHandler( - (FileInfo fi, OutputFormat f) => Task.FromResult(Archive.HandleInfo(fi, f)), + (FileInfo fi, ArchiveTool.OutputFormat f) => Task.FromResult(ArchiveTool.HandleInfo(fi, f)), pathArg, fOpt); return new Command("archive", "Inspect or extract the contents of a Unity archive (AssetBundle or web platform .data file).") @@ -283,7 +279,7 @@ static Command BuildArchiveCommand() static Command BuildSerializedFileCommand() { var pathArg = new Argument("filename", "The path of the SerializedFile").ExistingOnly(); - var fOpt = new Option(aliases: new[] { "--format", "-f" }, description: "Output format", getDefaultValue: () => OutputFormat.Text); + var fOpt = new Option(aliases: new[] { "--format", "-f" }, description: "Output format", getDefaultValue: () => SerializedFileTool.OutputFormat.Text); var externalRefsCommand = new Command("externalrefs", "List external file references in a SerializedFile.") { @@ -291,7 +287,7 @@ static Command BuildSerializedFileCommand() fOpt, }; externalRefsCommand.SetHandler( - (FileInfo fi, OutputFormat f) => Task.FromResult(SerializedFileCommands.HandleExternalRefs(fi, f)), + (FileInfo fi, SerializedFileTool.OutputFormat f) => Task.FromResult(SerializedFileTool.HandleExternalRefs(fi, f)), pathArg, fOpt); var objectListCommand = new Command("objectlist", "List all objects in a SerializedFile.") @@ -300,7 +296,7 @@ static Command BuildSerializedFileCommand() fOpt, }; objectListCommand.SetHandler( - (FileInfo fi, OutputFormat f) => Task.FromResult(SerializedFileCommands.HandleObjectList(fi, f)), + (FileInfo fi, SerializedFileTool.OutputFormat f) => Task.FromResult(SerializedFileTool.HandleObjectList(fi, f)), pathArg, fOpt); var headerCommand = new Command("header", "Show SerializedFile header information.") @@ -309,7 +305,7 @@ static Command BuildSerializedFileCommand() fOpt, }; headerCommand.SetHandler( - (FileInfo fi, OutputFormat f) => Task.FromResult(SerializedFileCommands.HandleHeader(fi, f)), + (FileInfo fi, SerializedFileTool.OutputFormat f) => Task.FromResult(SerializedFileTool.HandleHeader(fi, f)), pathArg, fOpt); var metadataCommand = new Command("metadata", "Show information from the metadata section of the SerializedFile (use `-f Json` for detailed information).") @@ -318,7 +314,7 @@ static Command BuildSerializedFileCommand() fOpt, }; metadataCommand.SetHandler( - (FileInfo fi, OutputFormat f) => Task.FromResult(SerializedFileCommands.HandleMetadata(fi, f)), + (FileInfo fi, SerializedFileTool.OutputFormat f) => Task.FromResult(SerializedFileTool.HandleMetadata(fi, f)), pathArg, fOpt); var serializedFileCommand = new Command("serialized-file", "Inspect a SerializedFile (scene, assets, etc.).") diff --git a/UnityDataTool/UnityDataTool.csproj b/UnityDataTool/UnityDataTool.csproj index 8426aa9..817bdb0 100644 --- a/UnityDataTool/UnityDataTool.csproj +++ b/UnityDataTool/UnityDataTool.csproj @@ -20,14 +20,14 @@ - + + + - - diff --git a/UnityDataTools.sln b/UnityDataTools.sln index 9a8dc2b..851dd1d 100644 --- a/UnityDataTools.sln +++ b/UnityDataTools.sln @@ -31,6 +31,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnityBinaryFormat", "UnityB EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnityDataModels", "UnityDataModels\UnityDataModels.csproj", "{E72FCD84-B200-4577-8440-788E33A4BEAF}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Archive", "Archive\Archive.csproj", "{53E144DE-48EB-4AA8-8BFD-7CF59EFCEB13}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SerializedFile", "SerializedFile\SerializedFile.csproj", "{0DA72219-4B14-4BF5-B777-C88E5D87CBE2}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -173,6 +177,30 @@ Global {E72FCD84-B200-4577-8440-788E33A4BEAF}.Release|x64.Build.0 = Release|Any CPU {E72FCD84-B200-4577-8440-788E33A4BEAF}.Release|x86.ActiveCfg = Release|Any CPU {E72FCD84-B200-4577-8440-788E33A4BEAF}.Release|x86.Build.0 = Release|Any CPU + {53E144DE-48EB-4AA8-8BFD-7CF59EFCEB13}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {53E144DE-48EB-4AA8-8BFD-7CF59EFCEB13}.Debug|Any CPU.Build.0 = Debug|Any CPU + {53E144DE-48EB-4AA8-8BFD-7CF59EFCEB13}.Debug|x64.ActiveCfg = Debug|Any CPU + {53E144DE-48EB-4AA8-8BFD-7CF59EFCEB13}.Debug|x64.Build.0 = Debug|Any CPU + {53E144DE-48EB-4AA8-8BFD-7CF59EFCEB13}.Debug|x86.ActiveCfg = Debug|Any CPU + {53E144DE-48EB-4AA8-8BFD-7CF59EFCEB13}.Debug|x86.Build.0 = Debug|Any CPU + {53E144DE-48EB-4AA8-8BFD-7CF59EFCEB13}.Release|Any CPU.ActiveCfg = Release|Any CPU + {53E144DE-48EB-4AA8-8BFD-7CF59EFCEB13}.Release|Any CPU.Build.0 = Release|Any CPU + {53E144DE-48EB-4AA8-8BFD-7CF59EFCEB13}.Release|x64.ActiveCfg = Release|Any CPU + {53E144DE-48EB-4AA8-8BFD-7CF59EFCEB13}.Release|x64.Build.0 = Release|Any CPU + {53E144DE-48EB-4AA8-8BFD-7CF59EFCEB13}.Release|x86.ActiveCfg = Release|Any CPU + {53E144DE-48EB-4AA8-8BFD-7CF59EFCEB13}.Release|x86.Build.0 = Release|Any CPU + {0DA72219-4B14-4BF5-B777-C88E5D87CBE2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0DA72219-4B14-4BF5-B777-C88E5D87CBE2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0DA72219-4B14-4BF5-B777-C88E5D87CBE2}.Debug|x64.ActiveCfg = Debug|Any CPU + {0DA72219-4B14-4BF5-B777-C88E5D87CBE2}.Debug|x64.Build.0 = Debug|Any CPU + {0DA72219-4B14-4BF5-B777-C88E5D87CBE2}.Debug|x86.ActiveCfg = Debug|Any CPU + {0DA72219-4B14-4BF5-B777-C88E5D87CBE2}.Debug|x86.Build.0 = Debug|Any CPU + {0DA72219-4B14-4BF5-B777-C88E5D87CBE2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0DA72219-4B14-4BF5-B777-C88E5D87CBE2}.Release|Any CPU.Build.0 = Release|Any CPU + {0DA72219-4B14-4BF5-B777-C88E5D87CBE2}.Release|x64.ActiveCfg = Release|Any CPU + {0DA72219-4B14-4BF5-B777-C88E5D87CBE2}.Release|x64.Build.0 = Release|Any CPU + {0DA72219-4B14-4BF5-B777-C88E5D87CBE2}.Release|x86.ActiveCfg = Release|Any CPU + {0DA72219-4B14-4BF5-B777-C88E5D87CBE2}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 9fa68c2933e4436fc5ebe5d32198f9fbe026f37c Mon Sep 17 00:00:00 2001 From: Andrew Skowronski Date: Mon, 6 Jul 2026 12:59:30 -0400 Subject: [PATCH 3/4] Better names for public API on ArchiveTool and SerializedFileTool --- Archive/ArchiveTool.cs | 10 +++++----- SerializedFile/SerializedFileTool.cs | 10 +++++----- UnityDataTool/Program.cs | 18 +++++++++--------- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/Archive/ArchiveTool.cs b/Archive/ArchiveTool.cs index 517b74b..6e1d19b 100644 --- a/Archive/ArchiveTool.cs +++ b/Archive/ArchiveTool.cs @@ -15,7 +15,7 @@ public enum OutputFormat Json } - public static int HandleExtract(FileInfo filename, DirectoryInfo outputFolder, string filter = null) + public static int ExtractContent(FileInfo filename, DirectoryInfo outputFolder, string filter = null) { try { @@ -45,7 +45,7 @@ err is NotSupportedException return 0; } - public static int HandleList(FileInfo filename, OutputFormat format) + public static int ListContent(FileInfo filename, OutputFormat format) { try { @@ -76,7 +76,7 @@ err is NotSupportedException return 0; } - public static int HandleHeader(FileInfo filename, OutputFormat format) + public static int PrintHeader(FileInfo filename, OutputFormat format) { var path = filename.ToString(); @@ -100,7 +100,7 @@ public static int HandleHeader(FileInfo filename, OutputFormat format) return 0; } - public static int HandleBlocks(FileInfo filename, OutputFormat format) + public static int ListBlocks(FileInfo filename, OutputFormat format) { var path = filename.ToString(); @@ -130,7 +130,7 @@ public static int HandleBlocks(FileInfo filename, OutputFormat format) return 0; } - public static int HandleInfo(FileInfo filename, OutputFormat format) + public static int PrintSummary(FileInfo filename, OutputFormat format) { var path = filename.ToString(); diff --git a/SerializedFile/SerializedFileTool.cs b/SerializedFile/SerializedFileTool.cs index c023546..f2ea459 100644 --- a/SerializedFile/SerializedFileTool.cs +++ b/SerializedFile/SerializedFileTool.cs @@ -15,7 +15,7 @@ public enum OutputFormat Json } - public static int HandleExternalRefs(FileInfo filename, OutputFormat format) + public static int ListExternalRefs(FileInfo filename, OutputFormat format) { // External references are read directly from the parsed metadata rather than via UnityFileSystemApi. // @@ -50,10 +50,10 @@ public static int HandleExternalRefs(FileInfo filename, OutputFormat format) return 0; } - public static int HandleObjectList(FileInfo filename, OutputFormat format) + public static int ListObjects(FileInfo filename, OutputFormat format) { // The object list is read directly from the parsed metadata rather than via UnityFileSystemApi. - // (See comment in HandleExternalRefs() for the reasons for doing it that way) + // (See comment in ListExternalRefs() for the reasons for doing it that way) if (!ValidateSerializedFile(filename.FullName, out var fileInfo)) return 1; @@ -78,7 +78,7 @@ public static int HandleObjectList(FileInfo filename, OutputFormat format) return 0; } - public static int HandleHeader(FileInfo filename, OutputFormat format) + public static int PrintHeader(FileInfo filename, OutputFormat format) { if (!ValidateSerializedFile(filename.FullName, out var fileInfo)) return 1; @@ -91,7 +91,7 @@ public static int HandleHeader(FileInfo filename, OutputFormat format) return 0; } - public static int HandleMetadata(FileInfo filename, OutputFormat format) + public static int PrintMetadata(FileInfo filename, OutputFormat format) { if (!ValidateSerializedFile(filename.FullName, out var fileInfo)) return 1; diff --git a/UnityDataTool/Program.cs b/UnityDataTool/Program.cs index 1761955..00e199e 100644 --- a/UnityDataTool/Program.cs +++ b/UnityDataTool/Program.cs @@ -225,7 +225,7 @@ static Command BuildArchiveCommand() filterOpt, }; extractArchiveCommand.SetHandler( - (FileInfo fi, DirectoryInfo o, string filter) => Task.FromResult(ArchiveTool.HandleExtract(fi, o, filter)), + (FileInfo fi, DirectoryInfo o, string filter) => Task.FromResult(ArchiveTool.ExtractContent(fi, o, filter)), pathArg, oOpt, filterOpt); var fOpt = new Option(aliases: new[] { "--format", "-f" }, description: "Output format", getDefaultValue: () => ArchiveTool.OutputFormat.Text); @@ -236,7 +236,7 @@ static Command BuildArchiveCommand() fOpt, }; listArchiveCommand.SetHandler( - (FileInfo fi, ArchiveTool.OutputFormat f) => Task.FromResult(ArchiveTool.HandleList(fi, f)), + (FileInfo fi, ArchiveTool.OutputFormat f) => Task.FromResult(ArchiveTool.ListContent(fi, f)), pathArg, fOpt); var headerArchiveCommand = new Command("header", "Display the header of a Unity Archive file.") @@ -245,7 +245,7 @@ static Command BuildArchiveCommand() fOpt, }; headerArchiveCommand.SetHandler( - (FileInfo fi, ArchiveTool.OutputFormat f) => Task.FromResult(ArchiveTool.HandleHeader(fi, f)), + (FileInfo fi, ArchiveTool.OutputFormat f) => Task.FromResult(ArchiveTool.PrintHeader(fi, f)), pathArg, fOpt); var blocksArchiveCommand = new Command("blocks", "Display the block list of a Unity Archive file.") @@ -254,7 +254,7 @@ static Command BuildArchiveCommand() fOpt, }; blocksArchiveCommand.SetHandler( - (FileInfo fi, ArchiveTool.OutputFormat f) => Task.FromResult(ArchiveTool.HandleBlocks(fi, f)), + (FileInfo fi, ArchiveTool.OutputFormat f) => Task.FromResult(ArchiveTool.ListBlocks(fi, f)), pathArg, fOpt); var infoArchiveCommand = new Command("info", "Display a high-level summary of a Unity Archive file.") @@ -263,7 +263,7 @@ static Command BuildArchiveCommand() fOpt, }; infoArchiveCommand.SetHandler( - (FileInfo fi, ArchiveTool.OutputFormat f) => Task.FromResult(ArchiveTool.HandleInfo(fi, f)), + (FileInfo fi, ArchiveTool.OutputFormat f) => Task.FromResult(ArchiveTool.PrintSummary(fi, f)), pathArg, fOpt); return new Command("archive", "Inspect or extract the contents of a Unity archive (AssetBundle or web platform .data file).") @@ -287,7 +287,7 @@ static Command BuildSerializedFileCommand() fOpt, }; externalRefsCommand.SetHandler( - (FileInfo fi, SerializedFileTool.OutputFormat f) => Task.FromResult(SerializedFileTool.HandleExternalRefs(fi, f)), + (FileInfo fi, SerializedFileTool.OutputFormat f) => Task.FromResult(SerializedFileTool.ListExternalRefs(fi, f)), pathArg, fOpt); var objectListCommand = new Command("objectlist", "List all objects in a SerializedFile.") @@ -296,7 +296,7 @@ static Command BuildSerializedFileCommand() fOpt, }; objectListCommand.SetHandler( - (FileInfo fi, SerializedFileTool.OutputFormat f) => Task.FromResult(SerializedFileTool.HandleObjectList(fi, f)), + (FileInfo fi, SerializedFileTool.OutputFormat f) => Task.FromResult(SerializedFileTool.ListObjects(fi, f)), pathArg, fOpt); var headerCommand = new Command("header", "Show SerializedFile header information.") @@ -305,7 +305,7 @@ static Command BuildSerializedFileCommand() fOpt, }; headerCommand.SetHandler( - (FileInfo fi, SerializedFileTool.OutputFormat f) => Task.FromResult(SerializedFileTool.HandleHeader(fi, f)), + (FileInfo fi, SerializedFileTool.OutputFormat f) => Task.FromResult(SerializedFileTool.PrintHeader(fi, f)), pathArg, fOpt); var metadataCommand = new Command("metadata", "Show information from the metadata section of the SerializedFile (use `-f Json` for detailed information).") @@ -314,7 +314,7 @@ static Command BuildSerializedFileCommand() fOpt, }; metadataCommand.SetHandler( - (FileInfo fi, SerializedFileTool.OutputFormat f) => Task.FromResult(SerializedFileTool.HandleMetadata(fi, f)), + (FileInfo fi, SerializedFileTool.OutputFormat f) => Task.FromResult(SerializedFileTool.PrintMetadata(fi, f)), pathArg, fOpt); var serializedFileCommand = new Command("serialized-file", "Inspect a SerializedFile (scene, assets, etc.).") From 3a81c2b3b002cdf8694a733c7432f1286c766ecd Mon Sep 17 00:00:00 2001 From: Andrew Skowronski <86242170+SkowronskiAndrew@users.noreply.github.com> Date: Mon, 6 Jul 2026 15:49:34 -0400 Subject: [PATCH 4/4] Improve wording Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 694ab90..f2bde65 100644 --- a/README.md +++ b/README.md @@ -101,7 +101,7 @@ flowchart TD ## Purpose of UnityFileSystemApi -UnityFileSystemApi is compiled from the Unity source code and exposes the core functionality to open and read the Unity Archive and Serialized File formats, exposed as a flexible, performant library. It exposes ability to navigates the TypeTrees inside a SerializedFile so objects can be read generically, without hardcoded type knowledge. +UnityFileSystemApi is compiled from the Unity source code and exposes the core functionality to open and read the Unity Archive and Serialized File formats as a flexible, performant library. It exposes the ability to navigate the TypeTrees inside a SerializedFile so objects can be read generically, without hardcoded type knowledge. It enables custom tools for binary2text-like output and efficient SQLite database generation.