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.
  2. Dismiss Notice

Find all perfabs which have a component on root in Unity Editor

Discussion in 'Editor & General Support' started by SurprisedPikachu, May 5, 2021.

  1. SurprisedPikachu

    SurprisedPikachu

    Joined:
    Mar 12, 2020
    Posts:
    84
    I have this piece of code which returns all the prefabs in the project that have a given component:
    Code (CSharp):
    1. private static Component[] GetAllPrefabs(Type t)
    2. {
    3.     string[] guids = AssetDatabase.FindAssets("t:Prefab");
    4.  
    5.     List<Object> all = guids
    6.         .Select(AssetDatabase.GUIDToAssetPath)
    7.         .Select(path => AssetDatabase.LoadAssetAtPath(path, t))
    8.         .Where(asset => asset != null)
    9.         .ToList();
    10.  
    11.     var prefabs = new List<Component>();
    12.  
    13.     foreach (Object o in all)
    14.     {
    15.         PrefabAssetType type = PrefabUtility.GetPrefabAssetType(o);
    16.         if (type == PrefabAssetType.MissingAsset || type == PrefabAssetType.NotAPrefab)
    17.             continue;
    18.  
    19.         if (o is Component comp)
    20.         {
    21.             if (comp.GetType() == t)
    22.                 prefabs.Add(comp);
    23.         }
    24.         else if (o is GameObject go)
    25.         {
    26.             Component c = go.GetComponent(t);
    27.             if (c != null)
    28.                 prefabs.Add(c);
    29.         }
    30.         else
    31.             Debug.LogError($"Could not add prefab {o} to list");
    32.     }
    33.  
    34.     return prefabs.ToArray();
    35. }
    36.  
    The problem is, it is slow. Loading every prefab to see if it is has the component or not takes too much time. (Lines 5-9)

    Is there any Unity API which I can use to improve the performance of this operation?
     
    RyhorKorneu likes this.
  2. RubberBandGames

    RubberBandGames

    Joined:
    Jul 20, 2020
    Posts:
    165
    Did you ever find a solution to this?
     
  3. sebastiengrenier

    sebastiengrenier

    Unity Technologies

    Joined:
    Jun 11, 2019
    Posts:
    87
    Have you tried looking at the Search API: https://docs.unity3d.com/ScriptReference/Search.SearchService.html? The Search API uses indexing which improves search performance a lot for those type of searches.

    Not only can you do searches using the Search window, you can leverage this API through scripts easily. For example, searching for prefabs with a component of type collider, you would do:
    Code (CSharp):
    1. public static Component[] YieldResults(Type t)
    2. {
    3.     var prefabs = new List<Component>();
    4.     ISearchList results = SearchService.Request($"p: t:prefab t:{t.Name}", SearchFlags.Synchronous);
    5.     foreach (var result in results)
    6.     {
    7.         var o = result.ToObject(t);
    8.         // Your code here...
    9.     }
    10.  
    11.     return prefabs.ToArray();
    12. }
    Bear in mind here I've used the parameter SearchFlags.Synchronous. We do not recommend using this flags, since Search is more effective when used asynchronously. However, it is there for quick and easy testing and to make it easy to replace your previous functions with this new API.
     
  4. RubberBandGames

    RubberBandGames

    Joined:
    Jul 20, 2020
    Posts:
    165
    This is great!

    But doesn't exist for our Unity version which is Unity 2020.3.34f1.
     
  5. sebastiengrenier

    sebastiengrenier

    Unity Technologies

    Joined:
    Jun 11, 2019
    Posts:
    87
    Yuchen_Chang likes this.