Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions Analyzer/Resources/AssetBundle.sql
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
-- the AssetBundle object, so this table is empty for Player and ContentDirectory builds.
-- For scene bundles the entry names the scene and points at the synthetic Scene object (see
-- AssetBundleHandler / SerializedFileSQLiteWriter).
CREATE TABLE IF NOT EXISTS assets(
CREATE TABLE IF NOT EXISTS assetbundle_assets(
object INTEGER,
name TEXT
);
Expand All @@ -18,22 +18,22 @@ CREATE TABLE IF NOT EXISTS assets(
-- * AssetBundleHandler: an asset's slice of the AssetBundle object's m_PreloadTable.
-- * SerializedFileSQLiteWriter: a scene object -> each object in the scene's SerializedFiles.
-- * PreloadDataHandler: the PreloadData object's m_Assets. PreloadData is a *separate* Unity
-- object (not part of the AssetBundle object) and also exists in Player builds, so this table
-- is NOT empty there; but those builds have no scene object, so PreloadDataHandler currently
-- attributes the rows to object id -1 (a known limitation).
CREATE TABLE IF NOT EXISTS asset_dependencies(
-- object (not part of the AssetBundle object) and also exists in Player builds (one per scene in its sharedAsset file),
-- so this table is NOT empty there; but those builds have no scene object, so PreloadDataHandler currently
-- attributes the rows to object id -1 (issue 81).
CREATE TABLE IF NOT EXISTS preload_dependencies(
object INTEGER,
dependency INTEGER
);

CREATE VIEW IF NOT EXISTS asset_view AS
CREATE VIEW IF NOT EXISTS assetbundle_asset_view AS
SELECT
a.name AS asset_name,
o.*
FROM assets a INNER JOIN object_view o ON o.id = a.object;
FROM assetbundle_assets a INNER JOIN object_view o ON o.id = a.object;

CREATE VIEW IF NOT EXISTS asset_dependencies_view AS
CREATE VIEW IF NOT EXISTS preload_dependencies_view AS
SELECT a.id, a.asset_name, a.asset_bundle, a.type, od.id dep_id, od.asset_bundle dep_asset_bundle, od.name dep_name, od.type dep_type
FROM asset_view a
INNER JOIN asset_dependencies d ON a.id = d.object
FROM assetbundle_asset_view a
INNER JOIN preload_dependencies d ON a.id = d.object
INNER JOIN object_view od ON od.id = d.dependency;
9 changes: 5 additions & 4 deletions Analyzer/Resources/Init.sql
Original file line number Diff line number Diff line change
Expand Up @@ -139,14 +139,14 @@ SELECT m.id material_id, m.name material_name, a.name material_path, m.asset_bun
FROM object_view m
INNER JOIN refs_view r ON m.id = r.object AND r.property_path = 'm_Shader'
INNER JOIN object_view s ON r.referenced_object = s.id
LEFT JOIN assets a ON m.id = a.object;
LEFT JOIN assetbundle_assets a ON m.id = a.object;

CREATE VIEW view_material_texture_refs AS
SELECT m.id material_id, m.name material_name, a.name material_path, m.asset_bundle material_asset_bundle, t.id texture_id, t.name texture_name, t.asset_bundle texture_asset_bundle
FROM object_view m
INNER JOIN refs_view r ON r.object = m.id AND property_type = 'Texture'
INNER JOIN object_view t ON r.referenced_object = t.id
LEFT JOIN assets a ON m.id = a.object
LEFT JOIN assetbundle_assets a ON m.id = a.object
WHERE m.type = 'Material';

-- Special-case type value for the fake Scene object that is sometimes inserted into the object table,
Expand All @@ -155,8 +155,9 @@ INSERT INTO types (id, name) VALUES (-1, 'Scene');

-- Database schema version. Bump when the schema changes in a way that tools relying on it
-- (e.g. find-refs) cannot read from an older database. 1 = normalized refs table (issue #44);
-- databases produced before versioning report 0.
PRAGMA user_version = 1;
-- 2 = renamed assets/asset_dependencies tables to assetbundle_assets/preload_dependencies
-- (issue #82); databases produced before versioning report 0.
PRAGMA user_version = 2;

PRAGMA synchronous = OFF;
PRAGMA journal_mode = MEMORY;
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@
namespace UnityDataTools.Analyzer.SQLite.Commands.SerializedFile
{
/* TABLE DEFINITION:
create table asset_dependencies
create table preload_dependencies
(
object INTEGER,
dependency INTEGER,
PRIMARY KEY (object, dependency)
);
*/
internal class AddAssetDependency : AbstractCommand
internal class AddPreloadDependency : AbstractCommand
{
protected override string TableName => "asset_dependencies";
protected override string TableName => "preload_dependencies";

protected override string DDLSource => Resources.AssetBundle;

Expand Down
20 changes: 10 additions & 10 deletions Analyzer/SQLite/Handlers/AssetBundleHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
namespace UnityDataTools.Analyzer.SQLite.Handlers;

// Processes the AssetBundle Unity object, which only exists in content built as AssetBundles.
// It fills the assets table from the object's m_Container (the bundle's explicit assets) and adds
// their dependencies from m_PreloadTable. Player and ContentDirectory builds have no AssetBundle
// object, so this handler never runs for them (asset_dependencies can still get rows from other
// sources there - see AssetBundle.sql).
// It fills the assetbundle_assets table from the object's m_Container (the bundle's explicit
// assets) and adds their dependencies from m_PreloadTable. Player and ContentDirectory builds
// have no AssetBundle object, so this handler never runs for them (preload_dependencies can still
// get rows from other sources there - see AssetBundle.sql).
public class AssetBundleHandler : ISQLiteHandler
{
SqliteCommand m_InsertCommand;
Expand All @@ -20,8 +20,8 @@ public class AssetBundleHandler : ISQLiteHandler
// This name must match the one SerializedFileSQLiteWriter derives from the scene's file name
// so both compute the same synthetic Scene object id. They only agree for
// BuildPipeline.BuildAssetBundles; for Scriptable Build Pipeline / Addressables and other
// pipelines the writer never creates the Scene object, so the assets row written below points
// at an object id that has no objects-table row (a dangling reference).
// pipelines the writer never creates the Scene object, so the assetbundle_assets row written
// below points at an object id that has no objects-table row (a dangling reference).
private Regex m_SceneNameRegex = new Regex(@"([^//]+)\.unity");

public void Init(SqliteConnection db)
Expand All @@ -32,13 +32,13 @@ public void Init(SqliteConnection db)

m_InsertCommand = db.CreateCommand();

m_InsertCommand.CommandText = "INSERT INTO assets(object, name) VALUES(@object, @name)";
m_InsertCommand.CommandText = "INSERT INTO assetbundle_assets(object, name) VALUES(@object, @name)";
m_InsertCommand.Parameters.Add("@object", SqliteType.Integer);
m_InsertCommand.Parameters.Add("@name", SqliteType.Text);

m_InsertDepCommand = db.CreateCommand();

m_InsertDepCommand.CommandText = "INSERT INTO asset_dependencies(object, dependency) VALUES(@object, @dependency)";
m_InsertDepCommand.CommandText = "INSERT INTO preload_dependencies(object, dependency) VALUES(@object, @dependency)";
m_InsertDepCommand.Parameters.Add("@object", SqliteType.Integer);
m_InsertDepCommand.Parameters.Add("@dependency", SqliteType.Integer);
}
Expand Down Expand Up @@ -93,10 +93,10 @@ public void Finalize(SqliteConnection db)
{
using var command = new SqliteCommand();
command.Connection = db;
command.CommandText = "CREATE INDEX asset_dependencies_object ON asset_dependencies(object)";
command.CommandText = "CREATE INDEX preload_dependencies_object ON preload_dependencies(object)";
command.ExecuteNonQuery();

command.CommandText = "CREATE INDEX asset_dependencies_dependency ON asset_dependencies(dependency)";
command.CommandText = "CREATE INDEX preload_dependencies_dependency ON preload_dependencies(dependency)";
command.ExecuteNonQuery();
}

Expand Down
6 changes: 3 additions & 3 deletions Analyzer/SQLite/Handlers/PreloadDataHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
namespace UnityDataTools.Analyzer.SQLite.Handlers;

// Processes the PreloadData object found in scene bundles. Its m_Assets list is recorded as the
// scene's dependencies (asset_dependencies), so it is meaningful only alongside a synthetic Scene
// object. This is AssetBundle-specific in practice: Player builds also contain a PreloadData
// scene's dependencies (preload_dependencies), so it is meaningful only alongside a synthetic
// Scene object. This is AssetBundle-specific in practice: Player builds also contain a PreloadData
// object but have no scene object, so ctx.SceneId is -1 there and the rows below are written
// against object id -1 (a limitation, not intended output). ContentDirectory builds have neither.
public class PreloadDataHandler : ISQLiteHandler
Expand All @@ -19,7 +19,7 @@ public void Init(SqliteConnection db)
{
m_InsertDepCommand = db.CreateCommand();
m_InsertDepCommand.Connection = db;
m_InsertDepCommand.CommandText = "INSERT INTO asset_dependencies(object, dependency) VALUES(@object, @dependency)";
m_InsertDepCommand.CommandText = "INSERT INTO preload_dependencies(object, dependency) VALUES(@object, @dependency)";
m_InsertDepCommand.Parameters.Add("@object", SqliteType.Integer);
m_InsertDepCommand.Parameters.Add("@dependency", SqliteType.Integer);
}
Expand Down
8 changes: 4 additions & 4 deletions Analyzer/SQLite/Writers/SerializedFileSQLiteWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ public class SerializedFileSQLiteWriter : IDisposable
// Build Pipeline / Addressables ("CAB-<hash of scene path>") or the Multi-Process Build
// Pipeline ("CAB-<scene GUID>"), nor player-build scenes ("level0", "level1", ...). For
// those builds no synthetic Scene object is created (see the scene handling in
// WriteSerializedFile), so the scene rows AssetBundleHandler writes into assets end up
// dangling and PreloadDataHandler attributes preload dependencies to SceneId -1.
// WriteSerializedFile), so the scene rows AssetBundleHandler writes into assetbundle_assets
// end up dangling and PreloadDataHandler attributes preload dependencies to SceneId -1.
private Regex m_RegexSceneFile = new(@"BuildPlayer-([^\.]+)(?:\.sharedAssets)?");

// Rebuilt for each serialized file: maps a PPtr's local m_FileID (0 = this file, 1..N = an
Expand Down Expand Up @@ -75,7 +75,7 @@ public class SerializedFileSQLiteWriter : IDisposable
private AddSerializedFile m_AddSerializedFileCommand = new AddSerializedFile();
private AddObject m_AddObjectCommand = new AddObject();
private AddType m_AddTypeCommand = new AddType();
private AddAssetDependency m_InsertDepCommand = new AddAssetDependency();
private AddPreloadDependency m_InsertDepCommand = new AddPreloadDependency();

private bool m_Initialized;
private SqliteConnection m_Database;
Expand Down Expand Up @@ -166,7 +166,7 @@ public void WriteSerializedFile(string relativePath, string fullPath, string con
// A scene has no single Unity object to represent it, yet a scene bundle lists the scene
// (by its .unity path) as the bundle's asset and other objects/preloads need something to
// hang off of. So for scene bundles we synthesize one "Scene" object per scene and use it
// as the target of the assets row (AssetBundleHandler) and of the scene's content and
// as the target of the assetbundle_assets row (AssetBundleHandler) and of the scene's content and
// preload dependencies (below and PreloadDataHandler). This only happens when the file
// name matches m_RegexSceneFile; see its LIMITATION note for the builds this misses (issue 81).
var match = m_RegexSceneFile.Match(relativePath);
Expand Down
4 changes: 2 additions & 2 deletions Documentation/analyze-examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -245,9 +245,9 @@ This is a large subject, see [Comparing Builds](comparing-builds.md).

UnityDataTool works on the output of a Unity build, which, by its very nature, only contains the crucial data needed to efficiently load built content in the Player. It does not include complete information about the assets and scenes in the project that was used to create that build. You may want to match content back to the original source asset or scene. For example if the size of an AssetBundle has unexpectedly changed between builds then you may want to track down which source assets could be responsible for that change. Or you may want to confirm that some particular image has been included in the build.

For AssetBundles partial asset information can be found in the m_Containers list, inside the AssetBundle object. This records assets that were explicitly added to AssetBundles. In the database this can be found in the `assets` table. However, assets that are included in the build implicitly (because they are referenced from the explicitly added assets) will not be recorded anywhere in the AssetBundle content.
For AssetBundles partial asset information can be found in the m_Containers list, inside the AssetBundle object. This records assets that were explicitly added to AssetBundles. In the database this can be found in the `assetbundle_assets` table. However, assets that are included in the build implicitly (because they are referenced from the explicitly added assets) will not be recorded anywhere in the AssetBundle content.

Similarly for a player build the only paths populated in the `assets` table are the scenes from the Build Profile Scene List. The paths of the assets in the sharedAsset files is not recorded anywhere in the build output.
For a player build the `assetbundle_assets` table is empty (player builds don’t contain an AssetBundle object), and the paths of assets in the sharedassets files are not recorded anywhere in the build output.

In many cases the source asset can be inferred based on your specific knowledge of your project, and how the build was configured. For example the level files in a Player build match the Scenes in the Build Profile Scene list. And the content of AssetBundles is driven from the assignment of specific assets to those AssetBundles (or Addressable groups), along with assets they depend on.

Expand Down
4 changes: 2 additions & 2 deletions Documentation/analyzer.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,14 @@ duplicated assets. It also lists all the AssetBundles where the asset was found.
If the `--skip-crc` option is used, there will be a lot of false positives in that view. Otherwise,
it should be very accurate because CRCs are used to determine if objects are identical.

## asset_view (AssetBundleProcessor)
## assetbundle_asset_view (AssetBundleProcessor)

This view lists all the assets that have been explicitly assigned to AssetBundles. The dependencies
that were automatically added by Unity at build time won't appear in this view. The columns are the
same as those in the *object_view* with the addition of the *asset_name* that contains the filename
of the asset.

## asset_dependencies_view (AssetBundleProcessor)
## preload_dependencies_view (AssetBundleProcessor)

This view lists the dependencies of all the assets. You can filter by id or asset_name to get all
the dependencies of an asset. Conversely, filtering by dep_id will return all the assets that
Expand Down
11 changes: 6 additions & 5 deletions ReferenceFinder/ReferenceFinderTool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@ public ReferenceTreeNode(long id)

public class ReferenceFinderTool
{
// Minimum analyze database schema version find-refs can read. The normalized refs table
// (issue #44) is version 1; databases produced before schema versioning report 0.
const long RequiredSchemaVersion = 1;
// Minimum analyze database schema version find-refs can read. Version 2 renamed the
// assets/asset_view tables this tool queries to assetbundle_assets/assetbundle_asset_view
// (issue #82), so an older database (version 1 or the pre-versioning 0) cannot be read.
const long RequiredSchemaVersion = 2;

SqliteCommand m_GetRefsCommand;
SqliteCommand m_GetObjectCommand;
Expand Down Expand Up @@ -137,7 +138,7 @@ int FindReferences(SqliteConnection db, string outputFile, IList<long> objectIds
m_Writer = toStdout ? Console.Out : new StreamWriter(outputFile);

m_GetRefsCommand = db.CreateCommand();
m_GetRefsCommand.CommandText = @"SELECT object, property_path, EXISTS (SELECT * FROM assets a WHERE a.object = r.object) FROM refs_view r WHERE referenced_object = @id";
m_GetRefsCommand.CommandText = @"SELECT object, property_path, EXISTS (SELECT * FROM assetbundle_assets a WHERE a.object = r.object) FROM refs_view r WHERE referenced_object = @id";
m_GetRefsCommand.Parameters.Add("@id", SqliteType.Integer);

// Resolve the 'm_Script' property path to its id once so the per-object script lookup below
Expand Down Expand Up @@ -190,7 +191,7 @@ FROM object_view o

ProcessReferences(objectIds[i], findAll);

command.CommandText = "SELECT asset_name, asset_bundle, serialized_file FROM asset_view WHERE id = @id";
command.CommandText = "SELECT asset_name, asset_bundle, serialized_file FROM assetbundle_asset_view WHERE id = @id";

foreach (var root in m_Roots)
{
Expand Down
2 changes: 1 addition & 1 deletion UnityDataTool.Tests/ExpectedDataGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public static void Generate(Context context)
@"SELECT
(SELECT COUNT(*) FROM animation_clips),
(SELECT COUNT(*) FROM asset_bundles),
(SELECT COUNT(*) FROM assets),
(SELECT COUNT(*) FROM assetbundle_assets),
(SELECT COUNT(*) FROM audio_clips),
(SELECT COUNT(*) FROM meshes),
(SELECT COUNT(*) FROM monoscripts),
Expand Down
2 changes: 1 addition & 1 deletion UnityDataTool.Tests/UnityDataToolAssetBundleTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ private void ValidateDatabase(string databasePath, bool withRefs)
@"SELECT
(SELECT COUNT(*) FROM animation_clips),
(SELECT COUNT(*) FROM asset_bundles),
(SELECT COUNT(*) FROM assets),
(SELECT COUNT(*) FROM assetbundle_assets),
(SELECT COUNT(*) FROM audio_clips),
(SELECT COUNT(*) FROM meshes),
(SELECT COUNT(*) FROM objects),
Expand Down
2 changes: 1 addition & 1 deletion UnityDataTool.Tests/UnityDataToolPlayerDataTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public async Task Analyze_PlayerData_DatabaseCorrect()
cmd.CommandText =
@"SELECT
(SELECT COUNT(*) FROM asset_bundles),
(SELECT COUNT(*) FROM assets),
(SELECT COUNT(*) FROM assetbundle_assets),
(SELECT COUNT(*) FROM objects),
(SELECT COUNT(*) FROM refs),
(SELECT COUNT(*) FROM serialized_files)";
Expand Down
Loading