Skip to content

"analyze" command - Support ContentLayout.json #99

Description

@SkowronskiAndrew

Why

UnityDataTool analyze can already process a ContentDirectory build (Unity 6.6+) into a SQLite database, but the result is incomplete in two important ways, and the build report directory contains a file — ContentLayout.json — that fills exactly those gaps.

  1. The analyzed data can't be traced back to source assets. ContentDirectory output contains no source information: every file is named by a content hash (e.g. c0152db4….cf), so the database records objects and files that a user cannot connect to anything in their project. ContentLayout.json carries the mapping from each built serialized file back to the source assets it came from, which is what makes the database actually meaningful for build analysis.

  2. References between files resolve incorrectly. In ContentDirectory builds the external-references table inside each SerializedFile holds symbolic .cfid placeholders rather than real filenames; the true file-to-file wiring lives in the build manifest (and its tool-friendly superset, ContentLayout.json). See Documentation/contentdirectory-format.md. Without that information, analyze records every cross-file reference as dangling, and features built on references — find-refs, the script_object_view — are broken for ContentDirectory builds.

  3. Large layouts deserve SQL access. For big builds ContentLayout.json gets large, and querying big JSON directly from scripts is inefficient. Its schema is intentionally SQL-friendly (arrays of homogeneous objects that map cleanly to relational tables), so importing it into the analyze database gives efficient, ad-hoc access from scripts or the command line — consistent with how the tool already treats Addressables build layout files. This is valuable even without the build content: analyzing just a ContentLayout.json on its own is a supported way to query a large layout (e.g. computing recursive dependencies from a source asset path).

What

When the input paths given to analyze include a ContentLayout.json (the C# model already exists in UnityDataModels/ContentLayout.cs), the tool should use it in two ways:

1. Import its content into the database

The information in ContentLayout.json becomes queryable tables/views in the analyze database, connected to the existing core data (serialized files, objects, references). The import is full-fidelity: every section of the file is represented — the per-serialized-file information (source assets, content hash, dependencies on other serialized files), the loadables information (loadable objects, loadable scenes, root assets), and the BinaryArtifacts graph.

Notes on scope of the import:

  • The default is to mirror the file's own structure, in particular keeping BinaryArtifacts in its generic form rather than post-processing it into a .resS/.resource-specific shape. The generic table is the standard place to record artifact sizes (including serialized-file sizes, which the core tables don't carry) and stays valid if future builds reference new kinds of data files. The schema design may still deviate if the generic shape turns out to make typical queries awkward — the built-in convenience views and documented example queries are the test for that.
  • The symbolic .cfid ID of each serialized file is preserved in the imported data, so the placeholder strings seen inside the SerializedFiles remain traceable after references are resolved.
  • The new tables/views must be created only when a ContentLayout.json is actually imported, so users analyzing AssetBundles or Player builds don't see a pile of empty ContentDirectory tables.
  • The initial version supports importing one ContentLayout.json per database. Multi-layout import (e.g. for comparing builds, like the existing multi-BuildReport support) is a possible future extension and is explicitly out of scope.

Alongside the schema, a new documentation page (e.g. Documentation/analyze-examples-contentlayout.md, linked from Documentation/analyze-examples.md) should give typical SQL queries for ContentDirectory builds: some that need only the layout tables (e.g. recursive dependencies from a source asset path), and some that combine layout and content tables (e.g. list all serialized files and objects that are the build output of a specific source asset such as an FBX, non-recursive).

2. Use it to resolve references

While analyzing the build's serialized files, the layout's dependency information is used to resolve each external reference to the actual .cf file it points at, instead of the .cfid placeholder recorded in the file itself. Files without layout coverage keep the current behavior (use the external-table path as-is).

The observable result: analyzing a ContentDirectory build together with its ContentLayout.json produces correct cross-file references — an empty dangling_refs table (aside from references to built-in files like unity default resources), and working find-refs chains such as the root ScriptableObject → dependent ScriptableObjects scenario in the LeadingEdge reference build.

3. Input validation and matching

analyze already accepts multiple file/directory paths, so passing the build output plus the ContentLayout.json (or the build report directory containing it) requires no new command-line surface. The rules for combining inputs:

  • Recognizing ContentDirectory content. .cf files (or a content<N>.archive) in the input identify ContentDirectory content. ContentDirectory output is flat, so no parent-directory searching is needed: if BuildManifestHash.txt is not already in the input, the tool automatically picks it up from the directory containing the ContentDirectory content (works for both loose builds and .archive files), if it exists there.
  • Exact-match guarantee. A ContentLayout.json is only used if its top-level BuildManifestHash matches the hash in the build output's BuildManifestHash.txt (a file guaranteed to exist in every ContentDirectory output folder). This prevents silently producing misleading results from a stale or unrelated layout. If a layout is on the input alongside ContentDirectory content but no BuildManifestHash.txt can be found, the analyze fails — an unverifiable layout is not used.
  • Multiple layouts on input are OK if one matches. If several ContentLayout.json files are found (e.g. the user pointed at their whole Library/BuildHistory folder — an intentionally supported convenience), pick the one whose hash matches and ignore the rest. If at least one layout is found but none match the build, fail the analyze with a clear "build does not match layout" error.
  • A layout alone is valid input. Analyzing only a ContentLayout.json (no build content) imports the layout tables and nothing else — the efficient-queries use case from the "Why" section.
  • ContentDirectory without a layout is allowed, with a warning. Partial analysis is still useful (e.g. inspecting shaders), so it proceeds, but prints a warning that the analysis is incomplete — specifically that reference information is broken and source-asset mapping is absent — and encourages rerunning with the ContentLayout.json path included. The unresolvable cross-file references land in dangling_refs, which exists precisely to catch such references without treating them as errors.
  • Only one ContentDirectory at a time. Analyzing two or more distinct ContentDirectory builds in one run is an error (detected via multiple BuildManifestHash.txt files). This avoids the same-filename collision problems of issue Provide a clear error message when more than 1 SerializedFile with the same name is analyzed #51 without trying to solve them. Mixing one ContentDirectory with non-ContentDirectory content (a Player build, AssetBundles) remains allowed, e.g. for duplicate-content detection.
  • Unsupported schema version is a hard error. If the layout's Version field is not the supported one, fail with a clear error naming the version. (v1 was not widely used, so no backward-compatible parsing is written until a real need appears.)

Scenario summary:

Input Result
ContentDirectory only OK + warning: missing ContentLayout.json
Subset of files from a ContentDirectory OK + same warning (recognized via the .cf extension)
Multiple ContentDirectories Error
ContentDirectory + matching ContentLayout.json OK
Subset of ContentDirectory files + matching ContentLayout.json OK if a BuildManifestHash.txt can be found for successful hash match; error if the layout cannot be validated
ContentDirectory + multiple ContentLayout.json OK if at least one matches the manifest hash; error if none match
ContentLayout.json only OK — layout tables only
Non-ContentDirectory content + ContentDirectory (+ optional layout) OK (warning if layout missing)
ContentLayout.json with unsupported Version Error

Out of scope

  • Importing multiple ContentLayout.json files into one database (future work, for build comparison).
  • Backward compatibility with older ContentLayout.json schema versions — the C# model tracks the latest version only (currently v2).
  • Solving the general multiple-builds-in-one-database problem (issue Provide a clear error message when more than 1 SerializedFile with the same name is analyzed #51).
  • Analyzing the raw build manifest (<hash>.json) directly; ContentLayout.json is the supported tooling input, the manifest schema is internal.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions