[#131] Support ContentLayout v3 (Unity 6.7) with v2 backward compatibility - #147
SkowronskiAndrew wants to merge 3 commits into
Conversation
…ility The Unity 6.7 ContentLayout.json schema (v3) renames ID to StableId (no .cfid extension), replaces ContentHash with ArtifactIndex, references loadables by index instead of ObjectIdHash, and drops the loadable AssetPath/OutputLFID fields (no more remapping into clusters). UnityDataTools.Models.ContentLayout now tracks v3; the v2 schema is preserved as a reference definition in UnityDataTools.Models.V2. Analyze accepts both versions: v2 files are upgraded in memory to the v3 model (ContentLayoutV2Upgrader), so a single write path and a single database schema serve both. The content_layout tables move to the v3 shape (loadable_index key, stable_id, artifact_index, is_root_asset holding the 1-based root position); the v2-only source data (asset_path, source_lfid) lands in extra columns that exist only in databases imported from a v2 layout. PRAGMA user_version bumped to 8. The previous v2 layout of the LeadingEdge build is archived at TestCommon/Data/ContentLayoutVersions/v2 as a permanent fixture, the LeadingEdge ContentDirectory reference data is regenerated with a 6.7 editor (v3 layout), and UnityFileSystemApi.dll is updated to a local 6.7 build (debug config, Windows only - the mac/linux libraries still need a 6.7 build).
Windows, Mac, Linux builds from release candidate build
|
|
||
| ```sql | ||
| SELECT * FROM content_layout_loadable_objects_view ORDER BY is_root_asset DESC, asset_path; | ||
| SELECT * FROM content_layout_loadable_objects_view ORDER BY is_root_asset DESC, name; |
There was a problem hiding this comment.
Removing the asset_path really reduces the usefulness of the content_layout_loadable_objects_view, because the asset_path really makes the loadable understandable.
For v2-based imports we can use the asset_path directly from the Loadable structure.
For v3 we need content_layout_loadable_objects_view to incorporate the asset_path from content_layout_source_assets based on the matching serialized file index. We only expect a single match per serialized_file_index (multiple entries are only expected for special cases, like MonoScript or built-in resources)
So it seems we probably need a version specific definition of the view.
| /// the PersistentManager at runtime and have no artifact. Only written when true; absent means false.</summary> | ||
| public bool IsBuiltIn; | ||
|
|
||
| /// <summary>The source assets included in this SerializedFile.</summary> |
There was a problem hiding this comment.
Part of the trickiness of handling the removal of source_asset is that this remains an array. So a LoadableObjectId, which truly can only come from a single single source asset, now has a pointer to the serialized file that contains it, which has room for 0-n source assets.
For regular cases there will be 1 and only 1 entry here. We cannot make it an single field (yet?) because there is a special case for MonoScripts (clustered) and perhaps the built in files.
The comment can be extended a bit to mention this is normally only single entry.
For the moment it is best if our queries that deal with LoadableObjectId join in the SourceAssets.
There was a problem hiding this comment.
Lets correct this at the same time, because it is relevant to my comments about v2/v3 differences for source_asset.
For v2 the above is true. For v3 we handle do NOT cluster assets together even if there is a circular reference. Circular references should still be avoided but they do not impact the layout, they only cause inefficiencies at loading time.
SkowronskiAndrew
left a comment
There was a problem hiding this comment.
Some comments related to loadable -> source_assets mapping that we should address.
…ions The loadables view is version-specific again: v2 selects the recorded asset_path directly, v3 derives it from the containing file's source assets (normally a single entry per file). find-refs reports the asset path for loadable chain roots as before. Also documents that SourceAssets normally holds one entry, and corrects the circular- reference note for 6.7 (no more clustering; loading-time cost only).
Summary
Fixes #131.
Unity 6.7 changes the
ContentLayout.jsonschema from version 2 to version 3:IDbecomesStableId(the bare identity hash, no.cfidextension),ContentHashis replaced byArtifactIndex,LoadableDependenciesandRootAssetsreference loadables by index instead ofObjectIdHash(which was deleted), and the loadable entries loseAssetPathandOutputLFID— 6.7 no longer remaps objects into clusters, soLFIDnow records the output-file id directly.This PR makes
analyzeaccept both versions with a single database schema, so the same queries work on output from Unity 6.6 and 6.7. A v2 file is upgraded in memory to the v3 model on import; the C# modelUnityDataTools.Models.ContentLayoutnow tracks v3, and the v2 schema stays available as a reference definition inUnityDataTools.Models.V2.Changes
Models (UnityDataModels)
ContentLayout.csupdated to the v3 schema (CurrentVersion = 3).ContentLayoutV2.csunder theUnityDataTools.Models.V2namespace.Analyzer
ContentLayoutParserpeeks atVersion(streaming read) and deserializes with the matching model; unsupported versions get a clear error naming versions 2 and 3.ContentLayoutV2Upgraderconverts a v2 layout to the v3 model: strips.cfidfrom the stable ids and resolves the hash-based references (ObjectIdHash,ContentHash) to indices. The v2-only per-loadable source data travels in a small side record.content_layout*tables move to the v3 shape (user_version7 → 8):content_layout_serialized_files:cfid→stable_id,content_hash→artifact_index(hash and filename are derived in the views via the artifact link).content_layout_loadable_objects: keyed byloadable_index(json array index);lfidtakes the v3 meaning (output-file id);is_root_assetstores the 1-based root input position (0 = not a root); the v2-only columnsasset_pathandsource_lfidexist only in databases imported from a v2 layout (the importer picks the DDL variant, so v3 databases carry no always-NULL legacy columns).content_layout_loadable_dependenciesreferencesloadable_index.find-refsidentifies loadable chain roots by GUID instead of the removed asset path.Test data and tests
TestCommon/Data/ContentLayoutVersions/v2as a permanent backward-compat fixture, with new tests (AnalyzeContentLayoutV2Tests) covering the upgrade path.UnityFileSystemApinative libraries are still 6.6-era. Reading the regenerated 6.7 data requires a 6.7 build of the library, so many CI tests are expected to fail until 6.7 builds of the dll/dylib/so land on this branch (tracked separately). The test results below are from a local run with a locally built 6.7 dll.Documentation
contentlayout.md: v3 member table, stable-id explanation, and a versioning section documenting the v2→v3 differences.contentlayout-database.md: updated column reference plus a "Layout version differences" section.contentdirectory-format.md: worked examples refreshed from the regenerated 6.7 build.analyzer-schema.md: user_version 8 row.Testing
dotnet test— full suite green on Windows (839 passed / 10 skipped): v2 fixture import, v3 layout-only and layout+content analyze, reference resolution,find-refsacross content files, build-history matching.🤖 Generated with Claude Code