Reference for the SQLite database produced by the analyze command. See
Analyzer for an overview of the library, and Example usage of
Analyze for worked queries.
Parts of the schema are documented on their own pages:
| Tables | Page |
|---|---|
content_layout* |
ContentLayout in the Analyze Database |
build_report* |
BuildReport |
addressables_build* |
Addressables Build Report Analysis |
- Start from the views. They join the tables into the presentations you normally want, and a
GUI tool such as DB Browser for SQLite can display them directly.
object_viewis the main entry point. - The database documents itself too. Short notes for the non-obvious columns are stored inside
the
CREATEstatements, sosqlite3 Analysis.db ".schema objects"shows them. This page is the full reference; the in-database notes are the reminder you get when you only have the.db. - Two columns hold
''rather than NULL when they have no value:serialized_files.archiveandobjects.game_object.object_viewmaps the former to NULL. Test for''when querying the tables directly. - Ids are analyzer-assigned.
objects.idand the ids that reference it exist only in the database. The Unity object id isobjects.object_id. - Two options change what gets populated.
--skip-referencesleavesrefs,dangling_refsandscript_object_viewempty.--skip-crcsets everyobjects.crc32to 0, which makesview_potential_duplicatesreport many false positives.
Core tables:
| Name | One row per |
|---|---|
objects |
Unity object found in the analyzed files |
types |
distinct Unity type name |
serialized_files |
SerializedFile analyzed |
archives |
Unity Archive analyzed |
refs |
reference from one object to another |
dangling_refs |
reference target that was never analyzed |
property_names |
distinct property path used by refs |
property_types |
distinct referenced type name used by refs |
Core views:
| Name | Purpose |
|---|---|
object_view |
every object with its type, file and archive names resolved |
refs_view |
refs with the property strings resolved |
dangling_refs_view |
each unresolved target and the objects referencing it |
view_breakdown_by_type |
object count and total size per type |
view_potential_duplicates |
objects that appear in more than one file |
view_material_shader_refs |
each Material and its Shader |
view_material_texture_refs |
each Material and its Textures |
AssetBundle and MonoScript:
| Name | Purpose |
|---|---|
assetbundle_assets |
assets explicitly assigned to an AssetBundle |
assetbundle_asset_view |
those assets with their object columns resolved |
preload_dependencies |
objects Unity preloads alongside another object |
preload_dependencies_view |
preload pairs with both sides resolved |
monoscripts |
C# class behind each MonoBehaviour / ScriptableObject |
monoscripts_view |
MonoScripts with their containing file |
script_object_view |
MonoBehaviours and ScriptableObjects with their C# type |
Type-specific views, each object_view plus extra columns:
| Name | Type |
|---|---|
animation_view |
AnimationClip |
audio_clip_view |
AudioClip |
mesh_view |
Mesh |
texture_view |
Texture2D |
shader_view |
Shader |
shader_subprogram_view |
Shader sub-programs |
shader_keyword_ratios |
Shader keyword impact on variant count |
view_breakdowns_shaders |
Shaders aggregated by name |
One row per Unity object discovered during analysis, holding the properties common to all types.
Query object_view instead unless you need the raw ids.
| Column | Type | Description |
|---|---|---|
id |
INTEGER | Analyzer-assigned id, unique across the database. Does not exist in the serialized data. Primary key. |
object_id |
INTEGER | The Unity local file id, serialized as m_PathID in object references (PPtrs). Signed 64-bit. Unique within its SerializedFile but not across files. |
serialized_file |
INTEGER | serialized_files.id of the file containing the object. |
type |
INTEGER | types.id. |
name |
TEXT | The Object.name property. Empty for the many object types that have no name. |
game_object |
INTEGER | objects.id of the GameObject that owns this object. Set only for components; '' otherwise. |
size |
INTEGER | Size in bytes, including any external .resS / .resource stream data belonging to the object. |
crc32 |
INTEGER | CRC of the object's serialized state, including its external stream data. Useful for detecting whether an object changed between builds. 0 for every object when --skip-crc was used. |
The Unity type names referenced by objects.type.
| Column | Type | Description |
|---|---|---|
id |
INTEGER | The Unity class id. -1 is a synthetic type added by analyze, see below. Primary key. |
name |
TEXT | The type name, e.g. Texture2D. |
Type -1 is Scene. A scene has no single Unity object that represents it, so analyze inserts a
synthetic Scene object for scene bundles in order to have something for the AssetBundle container
entry and the scene's preload dependencies to hang off.
One row per SerializedFile encountered during analysis.
| Column | Type | Description |
|---|---|---|
id |
INTEGER | Analyzer-assigned id. Primary key. |
archive |
INTEGER | archives.id of the Unity Archive containing this file, or '' when the file is not inside an archive. object_view maps '' to NULL. |
name |
TEXT | The file's name on disk, see below. |
The name is usually a technical, hash-based string rather than a readable path, because that is how the file is named on disk:
- Regular AssetBundles:
CAB-<MD4 hash of the AssetBundle name>. This is MD4, not Unity'sHash128(spooky hash), and the optional AssetBundle-filename hash is not part of it. - Scene bundles vary by build pipeline:
BuildPipeline.BuildAssetBundlesproducesBuildPlayer-<SceneName>; the Scriptable Build Pipeline and Addressables produceCAB-<hash of scene path>; the Multi-Process Build Pipeline producesCAB-<scene GUID>. - Player builds name scenes
level0,level1, ... in scene-list order.
A file recorded because it holds a dangling reference target also appears here,
with archive NULL and no objects of its own. In that case the lowercased file name is all that is
known about it.
One row per Unity Archive encountered during analysis. AssetBundles are archives, and compressed Player and ContentDirectory builds also keep their content in archives. A bare SerializedFile that is not inside an archive has no row here.
| Column | Type | Description |
|---|---|---|
id |
INTEGER | Analyzer-assigned id. Primary key. |
name |
TEXT | The archive's name on the file system. UNIQUE. |
file_size |
INTEGER | Size of the archive file in bytes. |
name is UNIQUE and case-sensitive because analyze supports a single build at a time: two archives
with the same name would make every query ambiguous. A duplicate is detected while writing and
reported as an error; the constraint is the durable backstop. See
Comparing Builds for how to analyze several builds.
Every reference between Unity objects (PPtrs), whether the two objects are in the same SerializedFile
or in different ones. On large builds this is by far the biggest table, so the property strings are
deduplicated into property_names and
property_types and only integer ids are stored here. Query
refs_view to get the strings back.
| Column | Type | Description |
|---|---|---|
object |
INTEGER | objects.id of the referencing object. |
referenced_object |
INTEGER | objects.id of the target, or dangling_refs.id when the target's file was not analyzed. |
property_path |
INTEGER | property_names.id. |
property_type |
INTEGER | property_types.id. |
Not populated when analyze is run with --skip-references.
When a reference points at an object whose SerializedFile was not part of the analyzed input, analyze
still assigns that target an object id but never writes an objects row for it.
dangling_refs records those targets, so the reference information is preserved and every object id
is accounted for: each id resolves to exactly one of objects or dangling_refs, never both.
| Column | Type | Description |
|---|---|---|
id |
INTEGER | The assigned object id. No objects row has this id. Primary key. |
object_id |
INTEGER | The target's local file id (m_PathID) within its SerializedFile. |
serialized_file |
INTEGER | serialized_files.id of the un-analyzed file. That row has archive NULL and no objects of its own. |
Common causes:
- Analyzing a single AssetBundle or a partial subset of a bundle group, so cross-bundle references point at bundles that were not analyzed.
- A Player build referencing
unity default resources- a built-in file that ships without TypeTrees and so cannot be analyzed. (Resources/unity_builtin_extrais built alongside your content and can be analyzed, but produces the same dangling references when it is not part of the analyzed set.) - A ContentDirectory build analyzed without its
ContentLayout.json, so the symbolic external references in the content files cannot be resolved. See ContentLayout in the Analyze Database.
Not populated when analyze is run with --skip-references.
Deduplicated lookup tables for the strings that refs would otherwise repeat on every row.
Both have the same shape:
| Column | Type | Description |
|---|---|---|
id |
INTEGER | Primary key, referenced by refs. |
name |
TEXT | The string. property_names holds property paths (e.g. m_Shader, m_Materials[0]); property_types holds referenced type names (e.g. Texture2D, MonoScript). |
Prefer refs_view over joining these by hand.
The main view: every object in the analyzed build output, with its type, SerializedFile and archive names resolved. The output could be AssetBundles, a ContentDirectory build, a Player build, or standalone SerializedFiles.
| Column | Type | Description |
|---|---|---|
id |
INTEGER | objects.id. |
object_id |
INTEGER | The Unity object id. |
archive |
TEXT | Name of the Unity Archive containing the object, or NULL when the source file was a bare SerializedFile. |
serialized_file |
TEXT | Name of the SerializedFile containing the object. |
type |
TEXT | The object's type name. |
name |
TEXT | The object's name, if it had one. |
game_object |
INTEGER | objects.id of the containing GameObject, if any. Mostly for components. |
size |
INTEGER | Size in bytes, e.g. 3343772. |
pretty_size |
TEXT | Size in a readable form, e.g. 3.2 MB. |
crc32 |
INTEGER | The object's CRC. |
refs with the property_path and property_type ids resolved to their strings. Use this
rather than joining the lookup tables yourself.
| Column | Type | Description |
|---|---|---|
object |
INTEGER | The referencing object's id. |
referenced_object |
INTEGER | The target's id. |
property_path |
TEXT | The property holding the reference, e.g. m_Shader. |
property_type |
TEXT | The referenced type, e.g. Texture2D. |
SELECT * FROM refs_view WHERE property_type = 'MonoScript';Each dangling target joined back to the object or objects that reference it: one row per (referencing object, dangling target) reference.
| Column | Type | Description |
|---|---|---|
source_id |
INTEGER | objects.id of the referencing object. |
source_serialized_file |
TEXT | The referencing object's file. |
source_object_id |
INTEGER | The referencing object's Unity object id. |
property_path |
TEXT | The property holding the reference. |
property_type |
TEXT | The referenced type. |
target_id |
INTEGER | dangling_refs.id of the unresolved target. |
target_serialized_file |
TEXT | Name of the file the target lives in. |
target_object_id |
INTEGER | The target's local file id. |
-- what does object 42 fail to resolve, and where should those objects have come from?
SELECT * FROM dangling_refs_view WHERE source_id = 42;Because the view joins refs, it is empty when analyze is run with --skip-references (in that mode
neither refs nor dangling_refs are populated).
Total number and size of the objects, aggregated by type, largest first.
| Column | Type | Description |
|---|---|---|
type |
TEXT | The type name. |
count |
INTEGER | Number of objects of this type. |
byte_size |
INTEGER | Total size in bytes. |
pretty_size |
TEXT | Total size in a readable form. |
Objects that are possibly included more than once in the build output. This happens when an asset is referenced from multiple AssetBundles but is not assigned to one: Unity then copies it into every bundle that references it.
| Column | Type | Description |
|---|---|---|
instances |
INTEGER | How many copies were found. |
name |
TEXT | The object's name. |
type |
TEXT | The object's type. |
pretty_total_size |
TEXT | Combined size of all copies, readable form. |
total_size |
INTEGER | Combined size of all copies in bytes. |
size |
INTEGER | Size of one copy in bytes. |
pretty_size |
TEXT | Size of one copy, readable form. |
in_files |
TEXT | The archives (or SerializedFiles) the copies were found in. |
Rows are grouped by name, type, size and crc32, so the view is normally very accurate. With
--skip-crc every crc32 is 0 and the view reports many false positives.
Each Material paired with the Shader it references, and with the Textures it references. Both include the Material's AssetBundle container path when it has one.
view_material_shader_refs: material_id, material_name, material_path, material_archive,
shader_id, shader_name, shader_archive.
view_material_texture_refs: material_id, material_name, material_path, material_archive,
texture_id, texture_name, texture_archive.
The assets an AssetBundle explicitly exposes: one row per entry in the AssetBundle object's
m_Container. Dependencies that Unity pulled in automatically at build time are not listed here,
see preload_dependencies.
| Column | Type | Description |
|---|---|---|
object |
INTEGER | objects.id of the asset. For a scene bundle this is the synthetic Scene object. |
name |
TEXT | The container path the asset is addressed by. |
This data comes from the AssetBundle Unity object, so the table is populated only for AssetBundle builds. Player and ContentDirectory builds have no such object and it is empty for them.
For a scene bundle the container entry names the scene (its .unity path) and points at the
synthetic Scene object. This applies to both BuildPipeline.BuildAssetBundles and Scriptable
Build Pipeline / Addressables scene bundles.
assetbundle_assets joined to object_view: the columns of
object_view plus asset_name, the container path.
The join is an INNER JOIN, so a container entry whose object is not in the objects table is
omitted. In practice that only happens when the object was genuinely not analyzed, for example it
lives in a bundle that was not part of the analyzed set. The underlying table still holds those rows.
Preload relationships as object to dependency pairs. A "dependency" here is an object that Unity
preloads or pulls in alongside another object.
| Column | Type | Description |
|---|---|---|
object |
INTEGER | objects.id. What this is depends on the build type, see below. |
dependency |
INTEGER | objects.id of the preloaded object, or dangling_refs.id when it was not analyzed. |
The rows come from the AssetBundle and PreloadData Unity objects, so the table is populated for
AssetBundle and Player builds, but not ContentDirectory builds, which have neither object. What
the object side is depends on the build:
- AssetBundle asset: the explicitly-assigned asset, with its dependencies taken from the
AssetBundle object's
m_PreloadTable. - Scene bundle: the synthetic
Sceneobject. Its dependencies are the scene's shared assets and the entries of the scene's PreloadData. This works for bothBuildPipeline.BuildAssetBundlesand Scriptable Build Pipeline / Addressables scene bundles. The scene's own content objects (GameObjects and so on) are not listed as dependencies, but they share the scene object'sserialized_file. - Player build: the
PreloadDataobject itself, because a Player build has no scene object to attach the dependencies to. A Player build has onePreloadDataper scene (in itssharedassetsN.assets) plus one inglobalgamemanagers.assetsfor the always-loaded set.
The dependency side often references an object analyze never recorded, most commonly objects in
unity default resources. Those ids are catalogued in dangling_refs.
A convenience view over preload_dependencies that resolves the ids: it
joins each row's object to assetbundle_asset_view and its dependency
to object_view. Columns: id, asset_name, archive, type, dep_id,
dep_archive, dep_name, dep_type.
Filter by id or asset_name for the dependencies of one asset, or by dep_id for everything that
depends on a given object - useful for working out why an object was included in a build.
Because of those inner joins the view is narrower than the underlying table:
- It only includes rows whose
objectis an AssetBundle asset or scene. Player-build rows hang off aPreloadDataobject rather than an AssetBundle asset, so they do not appear here - query thepreload_dependenciestable directly for those. - It drops rows whose
dependencyis a dangling id, because those have noobject_viewrow to join to.
The class information for all the C# types of MonoBehaviour objects in the build output, including ScriptableObjects: assembly name, C# namespace and class name.
monoscripts joined so you can see which AssetBundle or SerializedFile contains each MonoScript
object.
All the MonoBehaviour and ScriptableObject objects in the build output with their location, size and
precise C# type, built from the monoscripts and refs tables. Empty when analyze is run
with --skip-references.
Each of these has the same columns as object_view plus the ones listed.
AnimationClips.
| Column | Description |
|---|---|
legacy |
1 if it is a legacy animation, 0 otherwise |
events |
the number of events |
AudioClips.
| Column | Description |
|---|---|
bits_per_sample |
number of bits per sample |
frequency |
sampling frequency |
channels |
number of channels |
load_type |
Compressed in Memory, Decompress on Load or Streaming |
format |
compression format |
Meshes.
| Column | Description |
|---|---|
sub_meshes |
the number of sub-meshes |
blend_shapes |
the number of blend shapes |
bones |
the number of bones |
indices |
the number of vertex indices |
vertices |
the number of vertices |
compression |
1 if compressed, 0 otherwise |
rw_enabled |
1 if the mesh has the R/W Enabled option, 0 otherwise |
vertex_size |
number of bytes used by each vertex |
channels |
name and type of the vertex channels |
Texture2Ds.
| Column | Description |
|---|---|
width / height |
texture resolution |
format |
compression format |
mip_count |
number of mipmaps |
rw_enabled |
1 if the texture has the R/W Enabled option, 0 otherwise |
Shaders.
| Column | Description |
|---|---|
decompressed_size |
approximate size in bytes the shader needs at runtime when loaded |
sub_shaders |
the number of sub-shaders |
sub_programs |
the number of sub-programs (usually one per shader variant, stage and pass) |
unique_programs |
the number of unique programs (variants with identical programs share one program in memory) |
keywords |
list of all the keywords affecting the shader |
One row per shader sub-program. Same columns as shader_view plus:
| Column | Description |
|---|---|
api |
the graphics API, e.g. DX11, Metal, GLES |
pass |
the pass number of the sub-program |
pass_name |
the pass name, if available |
hw_tier |
the hardware tier (as defined in the Graphics settings) |
shader_type |
the type of shader, e.g. vertex, fragment |
sub_program |
the sub-program index for this pass and shader type |
keywords |
the shader keywords specific to this sub-program |
Helps determine which shader keywords are causing a large number of variants. Define a "program" as a unique combination of shader, sub-shader, hardware tier, pass number, API and shader type. Each row of this view is one program paired with one of its keywords.
| Column | Description |
|---|---|
shader_id |
the shader id |
name |
the shader name |
sub_shader |
the sub-shader number |
hw_tier |
the hardware tier |
pass |
the pass number |
api |
the graphics API |
pass_name |
the pass name, if available |
shader_type |
the type of shader |
total_variants |
total number of variants for this program |
keyword |
one of the program's keywords |
variants |
number of variants including this keyword |
ratio |
variants / total_variants |
Use ratio to judge how a keyword affects the variant count. At 0.5 the keyword is in half the
variants, which means it is not being stripped at all: every variant exists both with and without
it. Keywords with a ratio close to 0.5 are therefore the best stripping targets. A ratio close to 0
or 1 means the keyword is in almost none or almost all of the variants, and stripping it will not
make much difference.
All the shaders aggregated by name. instances indicates how many times the shader was found in the
data files. Also provides the total size per shader and the list of AssetBundles it was found in.
The database records which schema it was produced with in PRAGMA user_version. Commands that read
an existing database (currently only find-refs) compare against it to give
a clean error instead of failing on a missing table or column.
Any schema change - a new or changed table, view or column - must bump the pragma in
Analyzer/Resources/Init.sql and add a row here. Databases produced before versioning report 0.
| Version | Change |
|---|---|
| 1 | Normalized refs table (#44) |
| 2 | Renamed assets / asset_dependencies to assetbundle_assets / preload_dependencies (#82) |
| 3 | Renamed the asset_bundles table to archives, and the asset_bundle column/alias to archive (#68) |
| 4 | build_report_packed_asset_contents_view type column changed from numeric id to type name (#55) |
| 5 | Added the dangling_refs table and view (#85) |
| 6 | archives.name is UNIQUE (#51) |
| 7 | Unity 6.6 build_reports columns and build_report_content_* tables (#107); asset_name / asset_extension columns on build_report_source_assets (#110) |
| Topic | Page |
|---|---|
| Analyzer | The library, and how to extend it |
| analyze command | Running analyze and its options |
| Example usage of Analyze | Worked queries |
| ContentLayout in the Analyze Database | The content_layout* tables |
| BuildReport | The build_report* tables |
| Addressables Build Report Analysis | The addressables_build* tables |
| Comparing Builds | Analyzing more than one build |
| Using UnityDataTool with an AI Agent | Agent-oriented workflow |