Skip to content

Plugin to display dependencies between assets, files, assetgroups, etc. in a tree based view within the Unity editor.

License

MIT, Unknown licenses found

Licenses found

MIT
LICENSE
Unknown
LICENSE.meta
Notifications You must be signed in to change notification settings

innogames/asset-relations-viewer

Repository files navigation

Asset Relations Viewer

Plugin to display dependencies between assets, files, AddressableAssetGroups, etc. in a tree based view within the Unity editor.





Features

  • Standalone Editor UI without any external dependencies
  • View which dependencies an asset has to other assets
  • View which assets have the given asset as a dependency
  • Show thumbnails of all assets in the dependency tree
  • filter for Asset Names and Asset Types in displayed tree
  • Highlight if an asset is used in the project (going to be packed in the app)
  • Show path of where an asset is used exactly within a scene, prefab or asset
  • Display byte size of compressed asset together with overall size of dependency tree
  • Extendable by own dependency resolvers, for example to show addressables
  • Support for additional Connection- and NodeTypes which can be added via addons, for example:
    • Addressable Groups
    • Addressables
    • AssetBundles
    • LocaKeys
    • AssemblyDefinitions
    • Etc.



Installation

For Unity 2019.3 or later (Using Unity Package Manager)

Find the manifest.json file in the packages folder of your project and edit it to look like this:

{
  "dependencies": {
    "com.innogames.asset-relations-viewer": "https://github.com/innogames/asset-relations-viewer.git",
    ...
  },
}

If you are in production and not want to get automatic updates always use a tagged version like:

	...
    "com.innogames.asset-relations-viewer": "https://github.com/innogames/asset-relations-viewer.git#VERSION_TAG",
    ...



First Usage

  1. Select an asset within the unity project explorer
  2. Right click to open context menu for an asset
  3. Select the "Asset Relations Viewer/Open" menu item
  4. On Dialog for the first startup of AssetRelationsViewer click on yes
  5. Wait for the resolver to find all dependencies for all assets in the project which can take a while for a large project with many assets



Controls

Menu items

Menu items sorted from left to right.

Back button ("<<"): Button to go back to previous selected asset to view.
Thumbnail Size: Size of the thumbnails in pixels.
Node Depth: Depth of the shown tree structure.

Reload: Reloads the cache without update.
Update: Updates dependencies and refreshes view after asset has changed.
Save and Update: Saves the project before updating cache.
Clear Cache and Update: Clears cache before updating to force a complete rebuild of all caches.

Async Update: Enables update of cache being split in multiple frames. This enables Unity to properly unload and clean memory resulting in much less memory peak consumption at the cost of longer update times. Info
Unload Unused Assets: If Unused Assets should be unloaded during cache update. Doing so will result in Assets being reloaded multiple times during update resulting in less peak memory at the cost of longer update times.
Unload Interval: The interval at which unused assets should be unloaded.

**Show additional node information **: Displays size and also type of the nodes.
Show Thumbnails: Shows correct thumbnails on nodes if available.
Show nodes Once: To only show each node (Asset) once within the displayed tree.
Show hierarchy Once: To only show the same dependency hierarchy for a node once within the displayed tree.
Show referencers: If referencers (Assets that have the selected asset as a dependency) should be shown or not.
Show Property Pathes: Shows path of dependency (GameObject->Components->ClassMemberVariable).
Align Nodes: If all nodes of the same depth should be aligned horizontally in the displayed tree.
Hide Filtered Nodes: Hide all nodes that are filtered out instead of just graying them out.
Highlight packaged assets: Adds green highlight to nodes which are going to be packed into the app (Are actually used by the game).
Merge Relations: If a node has the same asset as a dependency multiple times, the same dependency is just shown once.

Node

s: If the selected node is an asset, it will be selected in the unity project explorer.
>: Sets node as currently selected node.

Dependency type list

The AssetRelationViewer can display several types of dependencies. In order for them to show up these need to be selected first.

After selecting a dependency type that is currently not loaded the Load caches button need to be clicked on in order to finally load the dependency types.
Unused dependency types can be unloaded by clicking on the U button.

L Dependency type is active and currently loaded.
R Dependency type got activated but needs to be loaded.
U Dependency type got deactivated and can be unloaded.
R Button Refreshes the dependencies just for this dependency type.

Dependency types

Asset->Asset by Object

Dependencies of assets to assets by a UnityEngine.Object reference.

Asset->File

Dependencies of assets to the file they are part of.
This is required since a file can have several sub assets meaning that an asset is not automatically the file itself even though most files only contain a single asset.
Note: Only the file itself has size information about the assets it contains. So in order to get size information with the "Show additional node information" this dependency type need to be enabled.

Scene GameObject->GameObject

Dependencies of GameObject to GameObjects within the currently loaded scene or prefab.
If a GameObject is selected as the viewed node only GameObject->GameObject dependencies are shown. The GameObject->GameObject dependency view can not be viewed together with other dependencies.
Note: If the opened scene/prefab changed after opening the AssetRelationViewer the cache needs to be refreshed.

AsmDef->AsmDef

Dependencies between AssemblyDefinitions to other AssemblyDefinitions as well as AssemblyDefinitionReferences to AssemblyDefinitions

Dependency types for Unity Addressables

The following dependency types are only available if the Unity Addressables addon is added to the project.

Asset->Asset by AssetReference

In addressables a different Object can be referenced by a so called AssetReference instead of UnityEngine.Object
To display these references this node type needs to be enabled.

AddressableAssetGroup->Asset

AddressableAssetGroups of the Addressable system contain a list of assets.
By enabling this dependency type these assets can be viewed as a dependency.

Asset->AddressableAssetGroup

Used to display the dependency of an asset to the AddressableAssetGroup it is part of.
This is basically the opposite direction of the AddressableAssetGroup->Asset dependency.
This can be used to display bidirectional dependencies between assets and AddressableAssetGroups when also the AddressableAssetGroup->Asset is enabled.

Note

Having both AddressableAssetGroup->Asset and Asset->AddressableAssetGroup enabled at the same time can lead to very large dependency trees if AssetBundles have a lot of dependencies to other AssetBundles.

Caching

Most dependency types are cached to only update the dependencies again if the file itself got changed.
This greatly reduces the startup time of the AssetRelationsViewer since for large projects finding all Asset->Asset dependencies can take several minutes. If a file needs to be updated is currently determined by the timestamp of the file but could be changed to in addition also take a file hash into account.

Location

The caches are stored in PROJECT_ROOT/Library/NodeDependencyCache/.
Depending on the project size these files can be several several megabytes in size.

Clearing the cache

The cache files can either be deleted manually or inside Unity under the Window/Node Dependency Cache/Clear Cache Files menu item.

Node search and filter

Node search

Since every type of node can be viewed in the AssetRelationViewer like Assets, Files, AddressableAssetGroups, AsmDefs, etc. is sometimes helpful to have a generic node search.
Only known nodes based on the activated dependency types are shown, meaning that only nodes found by any activated DependencyCaches are selectable.
Nodes can be searched for by name and by type.
Based on the filtered name and type the dropdown will show all available nodes to select.
This enables also to find nodes that are otherwise not findable in the explorer, like the Default-Material of Unity.
Once selected in the dropdown the current node can be shown in the AssetRelationsViewer by clicking Select.

Node hierarchy filter

To specifically filter for either a node name or node type the "Node hierarchy filter:" can be used.
Only the matching nodes will be highlighted and all others are grayed out.
In the example the dependency tree is filtered for "vertexLit".

Showing dependency pathes

In the AssetRelationsViewer it is possible to not only view dependencies between Asset->Asset for example but also exactly through with path the dependency exist.
In order to view the pathes "Show Property Pathes" needs to be activated.
Once active the whole path of the dependency (GameObject->Components->ClassMemberVariable) is shown in the hierarchy tree view.

Node handlers

GUI options specific to a node type.

Asset

Options specific to Assets.

Contains dropdown to select an asset in the project.
Sync to explorer: If selected the currently selected asset in the project explorer will be the one shown in the AssetRelationsViewer.

File

Options specific to Files.
Currently there are no specific options for them.

InSceneGameObject

Options for in scene GameObjects.

Contains dropdown to select a GameObject from the currently opened scene/prefab.
Sync to hierarchy: If selected the currently selected GameObject in the currently opened scene/prefab will be shown in the AssetRelationsViewer.

Async dependency update details

Doing the whole dependency search in one frame leads to a very high memory consumption since Unity cant really clean memory here. Even calling CG.Collect() several time during the search does not help.

For example, the peak memory consumption of a full update on our live project increases ~10GB when doing a full dependency search. With the async approach this is only increasing ~3GB.

This however is at the cost of increased execution times of about 2x. The reason for this is that Unity in this case automatically unloads unused assets (which are needed multiple times later) between frames and cleans up memory in general.

Troubleshooting

There can be cases where no tree is shown in the AssetRelationsViewer

  • Make sure a node (Asset) is selected to be shown
  • Make sure a dependency cache (AssetDependencyCache) and dependency resolver (ObjectDependencyResolver) is selected, otherwise no dependency can be found
  • After a code recompile the dependency cache needs to be updated by clicking on "Refresh"
  • Some dependency types might not update/work correctly when being in PlayMode
  • There might be some rare cases where the cache didn't get updated correctly. If there are dependencies missing which you are sure should be displayed sometimes also complete cache rebuild with a Clean and Refresh can help.

Standalone dependency cache

The dependency cache can be used without the AssetRelationsViewer.
This makes it possible to use the cache for other tools where dependency information between assets, files, etc. is required.
In the following example we find out which asset have a dependency on the BaseProductions prefab.

NodeDependencyLookupContext context = new NodeDependencyLookupContext();
ResolverUsageDefinitionList resolverList = new ResolverUsageDefinitionList();

// If we want to update the cache before we try to find references
bool shouldUpdate = false;

resolverList.Add<AssetDependencyCache, ObjectSerializedDependencyResolver>(true, shouldUpdate, shouldUpdate);
resolverList.Add<AssetToFileDependencyCache, AssetToFileDependencyResolver>(true, shouldUpdate, shouldUpdate);

NodeDependencyLookupUtility.LoadDependencyLookupForCaches(context, resolverList);

// Get guid for BaseProductions prefab
string[] assetGuids = AssetDatabase.FindAssets("t:prefab PrefabInstance 1");

// Get the node for the files guid
Node fileNode = context.RelationsLookup.GetNode(assetGuids[0], FileNodeType.Name);

// Iterate over all references of the filenode to find the assetnode referencing it
foreach (Connection referencer in fileNode.Referencers)
{
	if (referencer.Node.Type == AssetNodeType.Name)
	{
		// Find out who is referencing the assetnode
		foreach (Connection assetreferencer in referencer.Node.Referencers)
		{
			Debug.LogWarning($"[{referencer.Node.ConcreteType}]{referencer.Node.Name} " +
							 $"is directly referenced by [{assetreferencer.Node.ConcreteType}]{assetreferencer.Node.Name}");
		}
	}
}

Executing this would result in the following output
[GameObject]BaseProductions is directly referenced by [GameObject]ProductionTabContent

For this script to work in your own project the name and type of the asset in AssetDatabase.FindAssets() needs to be adapted accordingly to an asset that exists in your project.

Addons

Support to display different connection and node types can be added by addons.

Writing own addons to support custom Connection- and NodeTypes

Own addons can be also added so custom dependencies with any NodeType and dependency type can be added to be viewed inside the Asset Relations Viewer.
For an example how to create addons please have a look at the Addressables implementation.