From 8c61391e34c3dcc00dc75b7e9aa71e3ee530c182 Mon Sep 17 00:00:00 2001 From: Andrew Skowronski Date: Fri, 24 Jul 2026 16:46:44 -0400 Subject: [PATCH 1/2] [#119] Add AI agent guide and refresh user entry points - New Documentation/agent-guide.md: recommended workflow for AI agents analyzing a build (analyze -> query views -> drill down), the id vs object_id distinction, one-build-per-database, TypeTree requirements, the refs table, and a worked diagnose-a-bundle example. Linked from README, unitydatatool.md, AGENTS.md, and it replaces the pre-agent-era "Using AI tools" section of analyze-examples.md. - The --help documentation URL now pins to the release tag when the version has no pre-release suffix; main carries a -dev suffix and keeps linking to the docs on main. - README Downloads section points at GitHub Releases instead of the Actions tab. --- AGENTS.md | 3 + Documentation/agent-guide.md | 144 +++++++++++++++++++++++++++++ Documentation/analyze-examples.md | 15 +-- Documentation/unitydatatool.md | 1 + README.md | 7 +- UnityDataTool/Program.cs | 11 ++- UnityDataTool/UnityDataTool.csproj | 6 +- 7 files changed, 169 insertions(+), 18 deletions(-) create mode 100644 Documentation/agent-guide.md diff --git a/AGENTS.md b/AGENTS.md index 7cc600d..c03ff9a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -2,6 +2,9 @@ This file provides guidance to AI agents when working with code in this repository. +> Using the tool rather than working on it? To analyze a Unity build with UnityDataTool, see +> [Using UnityDataTool with an AI Agent](Documentation/agent-guide.md). + ## Project Overview UnityDataTools is a .NET 9.0 command-line tool for analyzing Unity build output (AssetBundles, Player builds, Addressables). It extracts data from Unity's proprietary binary formats into SQLite databases and human-readable text files. The tool showcases the UnityFileSystemApi native library and serves as both a production tool and reference implementation. diff --git a/Documentation/agent-guide.md b/Documentation/agent-guide.md new file mode 100644 index 0000000..2b3b7b9 --- /dev/null +++ b/Documentation/agent-guide.md @@ -0,0 +1,144 @@ +# Using UnityDataTool with an AI Agent + +AI agents (Claude Code, Codex, Cursor, and similar tools) are good at answering questions about a +Unity build when they are pointed at UnityDataTool: the `analyze` command turns the build output into +a SQLite database that an agent can query directly, and the other commands let it drill into +individual files and objects. This page is the recommended workflow, plus the handful of facts that +are not obvious from `--help` and tend to cost the most discovery time. It is written so it can be +pasted (or linked) into an agent's context, and it is just as useful for humans writing scripts. + +## The core loop + +1. **Analyze the build output into a database.** One build per database (see below). + + ``` + UnityDataTool analyze /path/to/build -o Analysis.db + ``` + +2. **Query the database.** Any SQLite client works. The `sqlite3` command-line shell is the most + convenient; if it is not installed, Python's standard library works without any extra setup: + + ``` + sqlite3 Analysis.db ".mode column" "SELECT * FROM view_breakdown_by_type LIMIT 15;" + ``` + + ``` + python -c "import sqlite3; [print(*r) for r in sqlite3.connect('Analysis.db').execute(\"SELECT type, count, pretty_size FROM view_breakdown_by_type LIMIT 15\")]" + ``` + +3. **Start from the views, not the raw tables.** The database ships with views that join the + underlying tables into directly useful shapes. `object_view` (one row per object, with resolved + type/archive/file names and `pretty_size`) and `view_breakdown_by_type` (count and total size per + object type) answer most first questions. List everything that is available with: + + ``` + sqlite3 Analysis.db "SELECT name FROM sqlite_master WHERE type = 'view' ORDER BY name;" + ``` + + The full schema is documented in the [Analyzer database reference](analyzer.md); worked example + queries are in [Example usage of Analyze](analyze-examples.md). + +4. **Drill down into specific files and objects.** Once a query has identified something + interesting, the other commands show the actual content: + * [`dump`](command-dump.md) prints an object's full serialized properties as text. + * [`serialized-file`](command-serialized-file.md) inspects a SerializedFile's header, object + list, and external references. + * [`archive`](command-archive.md) lists or extracts the contents of an AssetBundle or other + Unity archive. + +5. **Trace why something is in the build** with [`find-refs`](command-find-refs.md), which walks the + reference graph recorded in the database. + +## Facts that save time + +**Two different ids.** `object_view` (and `objects`) has both an `id` and an `object_id` column, and +the two drill-down commands take different ones: + +* `id` is a small sequential row number assigned by `analyze`, unique across the whole database. + `find-refs -i` takes this one. +* `object_id` is the object's serialized local file id (the `m_PathID` seen in references), a signed + 64-bit value that is only unique within its SerializedFile. `dump -i` takes this one. + +**One build per database.** `analyze` refuses input where two archives (or two standalone +SerializedFiles) have the same name, because queries would be ambiguous — this happens when a +directory contains several builds, or the same bundles built for multiple targets. Analyze each +build into its own database and query them separately ([Comparing Builds](comparing-builds.md) +shows patterns for diffing them). + +**TypeTrees are required.** Object contents can only be interpreted when the files contain TypeTree +metadata. AssetBundles include it by default; Player builds do not, so analyzing a Player build +typically reports `Files without TypeTrees` and those files contribute nothing to the database (a +run where every file is skipped produces a valid but empty database). To analyze Player data, build +with the `ForceAlwaysWriteTypeTrees` diagnostic switch — see +[Player Build Format](playerbuild-format.md). + +**References live in the `refs` table.** Each row records that one object references another: +`object` is the referencing object's `id`, `referenced_object` is the referenced object's `id`, and +`refs_view` adds the property path and type as strings. This is the raw data behind `find-refs`, +and it is often quicker to query it directly, e.g. "what references object 140": + +``` +sqlite3 Analysis.db "SELECT object, property_path FROM refs_view WHERE referenced_object = 140;" +``` + +**Empty names are normal.** Many object types (Transform, GameObject components in general) have no +`name`; `object_view.game_object` links components back to their named GameObject. + +## Worked example: diagnose a bundle + +Given the question "what is in this AssetBundle and does anything look wasteful?", this sequence +answers it. Analyze just the one file into a throwaway database: + +``` +UnityDataTool analyze /path/to/bundles -o bundle.db -p my.bundle +``` + +Then look at, in order: + +```sql +-- What is in it, by type +SELECT * FROM view_breakdown_by_type; + +-- The biggest individual objects +SELECT object_id, type, name, pretty_size FROM object_view ORDER BY size DESC LIMIT 20; + +-- Texture formats, sizes, and Read/Write flags (rw doubles runtime memory when enabled) +SELECT name, format, width, height, mip_count, rw_enabled, pretty_size FROM texture_view; + +-- Meshes with Read/Write enabled +SELECT name, vertices, rw_enabled, pretty_size FROM mesh_view; + +-- Objects that appear more than once (same name/type/size in different files) +SELECT * FROM view_potential_duplicates; +``` + +Interpretation notes: `rw_enabled = 1` on textures and meshes doubles their runtime memory cost and +is only needed when scripts access the data on the CPU. Rows in `view_potential_duplicates` that +span archives usually mean a shared dependency was not assigned to a common bundle — expected for +independent builds, actionable within one build. To see a suspicious object in full, dump it: + +``` +UnityDataTool dump /path/to/bundles/my.bundle -i --stdout +``` + +## Providing schema context to a chat-based AI + +When using a chat AI that cannot run commands itself, the same information has to be provided as +context. Dump the schema of your database into a text file and attach it before asking for queries: + +``` +sqlite3 Analysis.db ".schema" > schema_dump.sql.txt +``` + +Note that the produced database's schema shows bare table definitions; the meaning of the columns is +documented in the [Analyzer database reference](analyzer.md), which is also useful context. + +## Related documentation + +| Topic | Description | +|-------|-------------| +| [Command-line tool](unitydatatool.md) | All commands and their options | +| [Analyzer database reference](analyzer.md) | Tables, views, and their columns | +| [Example usage of Analyze](analyze-examples.md) | More worked queries | +| [Comparing builds](comparing-builds.md) | Finding what changed between two builds | +| [Overview of Unity Content](unity-content-format.md) | SerializedFiles, Archives, and TypeTrees | diff --git a/Documentation/analyze-examples.md b/Documentation/analyze-examples.md index 189cc07..e4565f2 100644 --- a/Documentation/analyze-examples.md +++ b/Documentation/analyze-examples.md @@ -76,17 +76,10 @@ Example queries against build report data — build summary, size by type, and o ## Example: Using AI tools to help write queries -This is not a tutorial on using AI tools. However one useful tip: - -Many AI tools let you provide context by uploading a file or copying text. They are helpful for crafting SQL statements and creating scripts. However by default they probably do not know what to expect inside a UnityDataTools SQLite database. - -To provide this information you could run this command that dumps the current schema into a text file. - -``` -sqlite3 Analysis.db ".schema" > schema_dump.sql.txt -``` - -Then provide that file as context, prior to asking it to write queries based on the available tables, views and columns. For example: *Help me write a command line calling sqlite3 for Analysis.db that will print the top 5 shaders by the size column. It will print the name, pretty_size and serialized_file.* +AI tools are a good fit for the analyze database, whether that is an AI agent running `analyze` and +querying the result itself, or a chat AI helping you write SQL. The recommended workflow, the schema +facts worth knowing up front, and tips for providing schema context to chat-based tools are collected +in [Using UnityDataTool with an AI Agent](agent-guide.md). ## Example: Finding AssetBundles containing a certain object type diff --git a/Documentation/unitydatatool.md b/Documentation/unitydatatool.md index 8da099e..e46c6e9 100644 --- a/Documentation/unitydatatool.md +++ b/Documentation/unitydatatool.md @@ -97,6 +97,7 @@ If you see a warning about `UnityFileSystemApi.dylib` not being verified, go to | [TextDumper Output Format](textdumper.md) | Understanding dump output | | [ReferenceFinder Details](referencefinder.md) | Reference chain output format | | [Analyze Examples](analyze-examples.md) | Practical database queries | +| [Using UnityDataTool with an AI Agent](agent-guide.md) | Recommended workflow for AI agents analyzing a build | | [Comparing Builds](comparing-builds.md) | Strategies for build comparison | | [Unity Content Format](unity-content-format.md) | TypeTrees and file formats | | [ContentLayout.json](contentlayout.md) | The content layout file produced by content directory builds | diff --git a/README.md b/README.md index 6d2981d..294330b 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,7 @@ New to Unity's data files or to UnityDataTool? These topics are a good place to | [Command-line tool](./Documentation/unitydatatool.md) | All commands and their options. | | [Analyzer & database schema](./Documentation/analyzer.md) | The SQLite database that `analyze` produces, including its tables and views. | | [Example queries](./Documentation/analyze-examples.md) | Worked examples of querying the analyze database. | +| [Using UnityDataTool with an AI agent](./Documentation/agent-guide.md) | The recommended workflow for AI agents (and scripts) analyzing a build. | | [Comparing builds](./Documentation/comparing-builds.md) | Finding what changed between two builds. | | [Addressables build reports](./Documentation/addressables-build-reports.md) | Analyzing Addressables JSON build reports. | | [Build reports](./Documentation/buildreport.md) | Importing a Unity BuildReport to map build output back to source assets. | @@ -120,13 +121,13 @@ shared test data doubles as convenient sample content for ad hoc use of the tool ## Downloads -Prebuilt Windows and Mac builds are available in the "Actions" tab. Each update to the main branch triggers a new build. +Prebuilt Windows and Mac builds are published on the [Releases page](https://github.com/Unity-Technologies/UnityDataTools/releases). Each release includes a zip per platform containing the `UnityDataTool` executable and the native libraries it needs. To use: 1. Download and unzip the build for your platform. -2. Run UnityDataTool from the extracted location, or add it to your system PATH. +2. Run UnityDataTool from the extracted location, or add that location to your system PATH. -Refer to the [commit history](https://github.com/Unity-Technologies/UnityDataTools/commits/main/) to see the recent improvements to the tool. +Each release describes what changed; refer to the [commit history](https://github.com/Unity-Technologies/UnityDataTools/commits/main/) for changes since the latest release. To try unreleased changes, [build from source](#how-to-build). ## Getting UnityFileSystemApi diff --git a/UnityDataTool/Program.cs b/UnityDataTool/Program.cs index 99c024e..0b47a94 100644 --- a/UnityDataTool/Program.cs +++ b/UnityDataTool/Program.cs @@ -35,8 +35,6 @@ public static async Task Main(string[] args) return r; } - const string DocumentationUrl = "https://github.com/Unity-Technologies/UnityDataTools/blob/main/Documentation/unitydatatool.md"; - static string BuildRootDescription() { var version = Assembly.GetExecutingAssembly() @@ -49,13 +47,20 @@ static string BuildRootDescription() if (plusIndex >= 0) version = version.Substring(0, plusIndex); + // Release builds have a bare version (e.g. "2.1.0") matching a git tag, so their + // documentation link can be pinned to the matching docs. Dev builds carry a pre-release + // suffix (e.g. "2.2.0-dev") and link to the latest docs on main instead. + var docsRef = version.Contains('-') || version == "unknown" ? "main" : $"v{version}"; + var documentationUrl = + $"https://github.com/Unity-Technologies/UnityDataTools/blob/{docsRef}/Documentation/unitydatatool.md"; + return "UnityDataTool inspects and analyzes Unity file formats, for example the content formats for AssetBundles, " + "Player and content directory builds. It can build a database of the Unity objects and their " + "references for analysis, dump objects as text, and examine " + "archive and SerializedFile internals.\n\n" + "Run 'UnityDataTool [command] --help' for detailed help on a specific command.\n\n" + - $"Documentation: {DocumentationUrl}\n" + + $"Documentation: {documentationUrl}\n" + $"Version: {version}"; } diff --git a/UnityDataTool/UnityDataTool.csproj b/UnityDataTool/UnityDataTool.csproj index e4fbab4..cb86c4d 100644 --- a/UnityDataTool/UnityDataTool.csproj +++ b/UnityDataTool/UnityDataTool.csproj @@ -7,7 +7,11 @@ 2.0.0 2.2.0.0 2.2.0.0 - 2.2.0 + + 2.2.0-dev From 960a170d4409a7fc94e1332b577797403e5b2795 Mon Sep 17 00:00:00 2001 From: Andrew Skowronski Date: Fri, 24 Jul 2026 16:54:34 -0400 Subject: [PATCH 2/2] Small doc follow up to #114 We don't need to recommend binary2text --hexfloat now that it is available in the dump command directly. --- Documentation/comparing-builds.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Documentation/comparing-builds.md b/Documentation/comparing-builds.md index 6bd3c28..49d78bb 100644 --- a/Documentation/comparing-builds.md +++ b/Documentation/comparing-builds.md @@ -324,7 +324,7 @@ This confirms our understanding that pixel data inside "red.png" is what caused # Special cases -In some rare cases the binary Serialized File is different between two builds, but the text "dump" is identical. - -* This can happen if the change happens in the header of the file, or in some padding bytes. Such cases are rare because the Serialized File format is quite stable, but it has happened when performance or stabilities improvements have been introduced that changed the header or padding. -* Sometimes float or double values might appear to be identical in the text representation, but there could be a difference in the actual binary representation. binary2text has a "-hexfloat" argument that addresses this issue. \ No newline at end of file +In some rare cases the binary Serialized File is different between two builds, but the text "dump" is identical. + +* This can happen if the change happens in the header of the file, or in some padding bytes. Such cases are rare because the Serialized File format is quite stable, but is a possibility if comparing files produced by different versions of Unity. +* Sometimes float or double values might appear to be identical in the decimal text representation, but there could be a difference in the actual binary representation. Specify the `--hexfloat` argument to dump to address this issue.