Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.

Asset Usage Detector - Find references to an asset/object [Open Source]

Discussion in 'Immediate Mode GUI (IMGUI)' started by yasirkula, May 31, 2016.

  1. KenDots

    KenDots

    Joined:
    May 26, 2020
    Posts:
    5
    Hello!

    Thanks a lot for this tool, it has been very helpful! I wrote a simple script that calls your tool to help me find assets that have no references. In my case, the goal is to find sprites that have sprite packing tags (we are using legacy sprite packer) but are not actually referenced in any scenes/prefabs in the project.

    I didn't see any easy way to get this info, so my script does a single search for each sprite in our project, which takes a very long time. I was wondering if I was missing an easier way to accomplish this. Here is my script:

    Code (CSharp):
    1.        
    2.         void FindUnusedTexturesWithTag()
    3.         {
    4.             string[] textureGUIDs = AssetDatabase.FindAssets("t:Texture");
    5.  
    6.             StringBuilder sb = new StringBuilder();
    7.             AssetUsageDetector assetUsageDetector = new AssetUsageDetector();
    8.  
    9.             foreach (string textureGUID in textureGUIDs)
    10.             {
    11.                 string texturePath = AssetDatabase.GUIDToAssetPath(textureGUID);
    12.                 AssetImporter assetImporter = AssetImporter.GetAtPath(texturePath);
    13.                 TextureImporter textureImporter = assetImporter as TextureImporter;
    14.  
    15.                 if (textureImporter == null) //could be a NativeAssetImporter
    16.                 {
    17.                     continue;
    18.                 }
    19.  
    20.                 if (!string.IsNullOrEmpty(textureImporter.spritePackingTag))
    21.                 {
    22.                     Texture texture = AssetDatabase.LoadAssetAtPath<Texture>(texturePath);
    23.  
    24.                     Object obj = texture;
    25.                     SearchResult searchResult = assetUsageDetector.Run(new AssetUsageDetector.Parameters()
    26.                     {
    27.                         objectsToSearch = new ObjectToSearchEnumerator( new List<ObjectToSearch>(new ObjectToSearch[] {new ObjectToSearch(obj)}) ).ToArray(),
    28.                         searchInScenes = SceneSearchMode.ScenesInBuildSettingsTickedOnly,
    29.                         searchInAssetsFolder = true,
    30.                         searchInAssetsSubset = null,
    31.                         excludedAssetsFromSearch = null,
    32.                         dontSearchInSourceAssets = false,
    33.                         excludedScenesFromSearch =  null,
    34.                         lazySceneSearch = false,
    35.                         noAssetDatabaseChanges = true,
    36.                         showDetailedProgressBar = false
    37.                     });
    38.  
    39.                     if (searchResult.NumberOfGroups <= 0)
    40.                     {
    41.                         Debug.Log(texturePath + " Not Referenced!");
    42.                         sb.AppendLine(texturePath + " Not Referenced!");
    43.                     }
    44.                     else
    45.                     {
    46.                         Debug.Log(texturePath);
    47.                     }
    48.                 }
    49.             }
    50.  
    51.             Debug.Log(sb.ToString());
    52.  
    53.             string tempPath = FileUtil.GetUniqueTempPathInProject();
    54.             StreamWriter writer = new StreamWriter(tempPath);
    55.             writer.Write(sb);
    56.             writer.Close();
    57.             UnityEditorInternal.InternalEditorUtility.OpenFileAtLineExternal(tempPath, 1);
    58.         }
    Any thoughts? It seems like the most obvious way to improve this is to search for many assets at once, but if I did that, I didn't really see a clear way to determine that a particular asset came back with no references. I had trouble figuring out how I would correlate a `SearchResult` (or lack of one) to a particular asset I searched.
     
  2. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,710
    AssetUsageDetector doesn't just say "Sprite is referenced from Scene A", it says "Sprite is referenced from object B's C variable in Scene A", that's why it is slower. But you don't need such detailed information. Searching all sprites at once would surely help; the returned SearchResult is a graph split into multiple groups (scenes, Assets folder, etc.). You'd have to traverse every node in that graph and mark the sprites that you encountered as used.

    A much better solution in your case would be to use Unity's AssetDatabase.GetDependencies function. AssetUsageDetector uses it to determine if a searched object is used in Scene A and only then it searches that scene in detail. You can simply iterate over each asset in your project (AssetDatabase.GetAllAssets, excluding your sprites), get its dependencies and mark any sprites that these dependencies point to.
     
    KenDots likes this.
  3. Noa3

    Noa3

    Joined:
    May 29, 2012
    Posts:
    83
    Thank you for the Tool!
    it helps me to understand a project from a Different Company really fast
     
    Last edited: Oct 24, 2020
    MarcSpraragen and yasirkula like this.
  4. florinel2102

    florinel2102

    Joined:
    May 21, 2019
    Posts:
    75
    Thanks a lot ! :)
     
    yasirkula likes this.
  5. SpicyCatGames

    SpicyCatGames

    Joined:
    Sep 30, 2019
    Posts:
    12
    Thank you so much, the only reason I was avoiding the use of UnityEvents too much and using C# events instead is because I was unable to find references properly, since the one built in unity gives a bunch of false results.
     
    yasirkula likes this.
  6. jcuriel_glu

    jcuriel_glu

    Joined:
    May 26, 2017
    Posts:
    16
    I'm currently using Unity version 2019.4.16f1 and am getting this error when I use the right click option "Search for References"


    AssetUsageDetector Error:
    System.ArgumentException: The specified path is not of a legal form (empty).
    at System.IO.Path.InsecureGetFullPath (System.String path) [0x00025] in <9577ac7a62ef43179789031239ba8798>:0
    at System.IO.Path.GetFullPathInternal (System.String path) [0x00000] in <9577ac7a62ef43179789031239ba8798>:0
    at System.IO.FileInfo.Init (System.String fileName, System.Boolean checkHost) [0x00007] in <9577ac7a62ef43179789031239ba8798>:0
    at System.IO.FileInfo..ctor (System.String fileName) [0x00014] in <9577ac7a62ef43179789031239ba8798>:0
    at (wrapper remoting-invoke-with-check) System.IO.FileInfo..ctor(string)
    at AssetUsageDetectorNamespace.AssetUsageDetector.AssetHasAnyReferenceInternal (System.String assetPath) [0x00099] in /Assets/Plugins/AssetUsageDetector/Editor/AssetUsageDetector.cs:942
    at AssetUsageDetectorNamespace.AssetUsageDetector.AssetHasAnyReference (System.String assetPath) [0x0003f] in /Assets/Plugins/AssetUsageDetector/Editor/AssetUsageDetector.cs:914
    at AssetUsageDetectorNamespace.AssetUsageDetector.Run (AssetUsageDetectorNamespace.AssetUsageDetector+Parameters searchParameters) [0x00a04] in /Assets/Plugins/AssetUsageDetector/Editor/AssetUsageDetector.cs:415
    Searching references of:
    ButtonPrimary (UnityEngine.GameObject)
    ButtonPrimary (UnityEngine.RectTransform)
    ButtonPrimary (UnityEngine.UI.Button)
    ButtonPrimary (UnityEngine.UI.LayoutElement)
    ButtonPrimary (UIAudioHelper)
    UnityEngine.Debug:LogError(Object, Object)
    AssetUsageDetectorNamespace.AssetUsageDetector:Run(Parameters) (at Assets/Plugins/AssetUsageDetector/Editor/AssetUsageDetector.cs:562)
    AssetUsageDetectorNamespace.AssetUsageDetectorWindow:InitiateSearch() (at Assets/Plugins/AssetUsageDetector/Editor/AssetUsageDetectorWindow.cs:669)
    AssetUsageDetectorNamespace.AssetUsageDetectorWindow:OnGUI() (at Assets/Plugins/AssetUsageDetector/Editor/AssetUsageDetectorWindow.cs:540)
    UnityEngine.GUIUtility: ProcessEvent(Int32, IntPtr) (at /Users/bokken/buildslave/unity/build/Modules/IMGUI/GUIUtility.cs:197)
     
  7. nandovilla

    nandovilla

    Joined:
    Jun 22, 2016
    Posts:
    7
    Hey yasirkula, thank you for this great tool!

    In Unity 2019.1, the text size in the search result is too small:

    upload_2021-6-30_10-48-33.png

    Is there anything I can do to fix this?

    Cheers!
     
  8. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,710
    lol that really is too small. Can you comment out this line? If it works, I'd appreciate it if you could add
    Debug.Log(m_boxGUIStyle.fontSize + " " + GUI.skin.button.fontSize);
    above it and tell me the logged values.
     
  9. nandovilla

    nandovilla

    Joined:
    Jun 22, 2016
    Posts:
    7
    It works!

    upload_2021-6-30_14-46-22.png

    The logged values are 9 and 0.

    Thank you for the quick reply!

    Cheers!
     
    yasirkula likes this.
  10. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,710
    I'm not sure if it was a Unity 2019.1 bug or an issue that occurs on high dpi screens (but why would font size return 0). If, sometime in the future, you get the chance to test the plugin on newer Unity versions (2019 LTS or newer), please let me know of the results.
     
  11. nandovilla

    nandovilla

    Joined:
    Jun 22, 2016
    Posts:
    7
    Tested on 2019 LTS and it works perfectly! Thank you again!!
     
    yasirkula likes this.
  12. adamgolden

    adamgolden

    Joined:
    Jun 17, 2019
    Posts:
    1,339
    This helped me today finding references buried in properties of child assets of some 3rd party scriptable objects ..it would have taken me a long time to track them down without it. Thanks! :)
     
    yasirkula likes this.
  13. Chris-Ender

    Chris-Ender

    Joined:
    May 23, 2015
    Posts:
    12
    Great work yasirkula!

    I have some leftover third party assets from the store in a project and want to find any references in the project. So I drag the folder of this asset into the search of the AssetUsageDetector window and it produces lots of search results. It would be really helpful to be able to exclude all results within this third party asset folder and its subdirectories. Of course I am interested where this third party plugin is used and not in the dependencies within the plugin.
    Is this possible?

    Kind Regards,
    Chris
     
  14. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,710
    The
    Don't search "SEARCHED OBJECTS" themselves for references
    option does that. It's enabled by default but you may have disabled it in the past.
     
  15. Chris-Ender

    Chris-Ender

    Joined:
    May 23, 2015
    Posts:
    12
    Hi yasirkula,

    I have this option enabled, but it is not working for directories. I also tried to set the folder in the
    "Don't search following asset(s)"
    option. I tried the free assets
    MRTK
    and
    Oculus
    and old
    TextMesh Pro
    . For example if I do not use a TextMesh Pro Label at all I expect not see any search results. My intention is to safely e.g. remove an asset when it is not referenced anywhere. Is this possible?

    Kind Regrads,
    Chris
     
  16. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,710
    "Don't search following asset(s)" should actually work but it won't exclude scenes from search. To exclude scenes, you should use "Don't search in following scene(s)" instead.
     
  17. LuisAlarconGames

    LuisAlarconGames

    Joined:
    Jun 3, 2021
    Posts:
    5
    This was a lifesaver, amazing work, thanks a lot!
     
    yasirkula likes this.
  18. bacabrother

    bacabrother

    Joined:
    Aug 11, 2015
    Posts:
    3
    Thanks, great asset
     
  19. fleity

    fleity

    Joined:
    Oct 13, 2015
    Posts:
    256
    I have been trying to use this asset to find usages of operator subgraphs in visual effect graph assets.
    If I manually search with a text editor for the operators guid I can find it in the graphs .vfx file but the asset reports none found. Should it be working or am I doing something wrong?
     

    Attached Files:

  20. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,710
    Shader Graph assets are parsed. I think .vfx assets also need to be parsed, I'll check it out.
     
  21. fleity

    fleity

    Joined:
    Oct 13, 2015
    Posts:
    256
    thanks you so much, let me know if I can help / provide an example :)
     
    yasirkula likes this.
  22. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,710
    @fleity Wanted to let you know that I could reproduce the issue. There are two issues as it seems: the first is, right clicking a VFX Graph file and selecting "Select Dependencies" won't select the desired dependencies (AssetUsageDetector optimizes its search using that feature). The second is, iterating over a VFX Graph asset with SerialziedObject doesn't seem to yield the desired dependencies either. So I'll be accessing the VFX Graph API or use reflection to find those reflections.
     
    fleity likes this.
  23. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,710
    Better late than never! I've pushed an update to GitHub and Asset Store version is pending review.
     
    fleity likes this.
  24. fleity

    fleity

    Joined:
    Oct 13, 2015
    Posts:
    256
    Just tested it, works like a charm. Thank you very much.
     
    yasirkula likes this.
  25. sTs_28

    sTs_28

    Joined:
    Jul 15, 2015
    Posts:
    8
    Hi seems like plugin doest support [SerializeReference] members, i have SO

    Code (CSharp):
    1. Container : ScriptableObject
    2. {
    3.      [SerializeReference] A Instance;
    4. }
    5.  
    6. public class A
    7. {
    8.   [SerializeField] private AssetReferenceSprite _referenceSprite;
    9.   [SerializeField] private Sprite _sprite;
    10. }
    then searching for sprite doesn find match addressable or not.
     
  26. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,710
    @sTs_28 I couldn't reproduce the issue with your test case using latest version of the plugin on 2021.3.18f1 without Addressables package. The reference I've assigned to _sprite property was successfully found.