Search Unity

  1. Unity 2020.2 has been released.
    Dismiss Notice
  2. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    Dismiss Notice

EDITOR: Want to check all prefabs in a project for an attached MonoBehaviour

Discussion in 'Scripting' started by GarthSmith, Jun 22, 2014.

  1. GarthSmith

    GarthSmith

    Joined:
    Apr 26, 2012
    Posts:
    1,240
    I want to delete a script that I think isn't being used anymore. Is there a way I can get a list of every prefab in the project? I just want to run through all the prefabs and check if a certain script is attached.
     
    Alshan likes this.
  2. GarthSmith

    GarthSmith

    Joined:
    Apr 26, 2012
    Posts:
    1,240
    Another thing, is there a way to search all prefabs for missing MonoBehaviours? If I delete a script that is attached to some prefab, the prefab then gets a missing MonoBehaviour. Is there a way I can find all those prefabs in the project?
     
    Last edited: Jun 22, 2014
  3. hpjohn

    hpjohn

    Joined:
    Aug 14, 2012
    Posts:
    2,160
    Hey, I was bored, so I made this.
    Code (CSharp):
    1. //Assets/Editor/SearchForComponents.cs
    2. using UnityEngine;
    3. using UnityEditor;
    4. using System.Collections;
    5. using System.Collections.Generic;
    6.  
    7. public class SearchForComponents : EditorWindow {
    8.    [MenuItem( "EDITORS/Search For Components" )]
    9.    static void Init () {
    10.      SearchForComponents window = (SearchForComponents) EditorWindow.GetWindow( typeof( SearchForComponents ) );
    11.      window.Show();
    12.      window.position = new Rect( 20, 80, 400, 300 );
    13.    }
    14.  
    15.  
    16.    string[] modes = new string[] { "Search for component usage", "Search for missing components" };
    17.  
    18.    List<string> listResult;
    19.    int editorMode, editorModeOld;
    20.    MonoScript targetComponent, lastChecked;
    21.    string componentName = "";
    22.    Vector2 scroll;
    23.  
    24.    void OnGUI () {
    25.      GUILayout.Space( 3 );
    26.      int oldValue = GUI.skin.window.padding.bottom;
    27.      GUI.skin.window.padding.bottom = -20;
    28.      Rect windowRect = GUILayoutUtility.GetRect( 1, 17 );
    29.      windowRect.x += 4;
    30.      windowRect.width -= 7;
    31.      editorMode = GUI.SelectionGrid( windowRect, editorMode, modes, 2, "Window" );
    32.      GUI.skin.window.padding.bottom = oldValue;
    33.  
    34.      if ( editorModeOld != editorMode ) {
    35.        editorModeOld = editorMode;
    36.        listResult = new List<string>();
    37.        componentName = targetComponent == null ? "" : targetComponent.name;
    38.        lastChecked = null;
    39.      }
    40.  
    41.      switch ( editorMode ) {
    42.        case 0:
    43.          targetComponent = (MonoScript) EditorGUILayout.ObjectField( targetComponent, typeof( MonoScript ), false );
    44.  
    45.          if ( targetComponent != lastChecked ) {
    46.            lastChecked = targetComponent;
    47.            componentName = targetComponent.name;
    48.            AssetDatabase.SaveAssets();
    49.            string targetPath = AssetDatabase.GetAssetPath( targetComponent );
    50.            string[] allPrefabs = GetAllPrefabs();
    51.            listResult = new List<string>();
    52.            foreach ( string prefab in allPrefabs ) {
    53.              string[] single = new string[] { prefab };
    54.              string[] dependencies = AssetDatabase.GetDependencies( single );
    55.              foreach ( string dependedAsset in dependencies ) {
    56.                if ( dependedAsset == targetPath ) {
    57.                  listResult.Add( prefab );
    58.                }
    59.              }
    60.            }
    61.          }
    62.          break;
    63.        case 1:
    64.          if ( GUILayout.Button( "Search!" ) ) {
    65.            string[] allPrefabs = GetAllPrefabs();
    66.            listResult = new List<string>();
    67.            foreach ( string prefab in allPrefabs ) {
    68.              UnityEngine.Object o = AssetDatabase.LoadMainAssetAtPath( prefab );
    69.              GameObject go;
    70.              try {
    71.                go = (GameObject) o;
    72.                Component[] components = go.GetComponentsInChildren<Component>( true );
    73.                foreach ( Component c in components ) {
    74.                  if ( c == null ) {
    75.                    listResult.Add( prefab );
    76.                  }
    77.                }
    78.              } catch {
    79.                Debug.Log( "For some reason, prefab " + prefab + " won't cast to GameObject" );
    80.  
    81.              }
    82.            }
    83.          }
    84.          break;
    85.      }
    86.  
    87.      if ( listResult != null ) {
    88.        if ( listResult.Count == 0 ) {
    89.          GUILayout.Label( editorMode == 0 ? ( componentName == "" ? "Choose a component" : "No prefabs use component " + componentName ) : ( "No prefabs have missing components!\nClick Search to check again" ) );
    90.        } else {
    91.          GUILayout.Label( editorMode == 0 ? ( "The following prefabs use component " + componentName + ":" ) : ( "The following prefabs have missing components:" ) );
    92.          scroll = GUILayout.BeginScrollView( scroll );
    93.          foreach ( string s in listResult ) {
    94.            GUILayout.BeginHorizontal();
    95.            GUILayout.Label( s, GUILayout.Width( position.width / 2 ) );
    96.            if ( GUILayout.Button( "Select", GUILayout.Width( position.width / 2 - 10 ) ) ) {
    97.              Selection.activeObject = AssetDatabase.LoadMainAssetAtPath( s );
    98.            }
    99.            GUILayout.EndHorizontal();
    100.          }
    101.          GUILayout.EndScrollView();
    102.        }
    103.      }
    104.    }
    105.  
    106.    public static string[] GetAllPrefabs () {
    107.      string[] temp = AssetDatabase.GetAllAssetPaths();
    108.      List<string> result = new List<string>();
    109.      foreach ( string s in temp ) {
    110.        if ( s.Contains( ".prefab" ) ) result.Add( s );
    111.      }
    112.      return result.ToArray();
    113.    }
    114. }
    Enjoy!
     
    Last edited: Mar 12, 2015
    aduca9999, vedram, hwnyam and 6 others like this.
  4. GarthSmith

    GarthSmith

    Joined:
    Apr 26, 2012
    Posts:
    1,240
    Hey hpjohn, I just wanted to say I appreciate the script! I haven't had a chance to go through it line-by-line yet, but some preliminary testing indicates that it works like a charm.

    Our project is like over a thousand scripts and nearing a thousand prefabs at this point. Housekeeping is becoming a pain. Thanks for bringing order to this chaos!
     
  5. hpjohn

    hpjohn

    Joined:
    Aug 14, 2012
    Posts:
    2,160
    Don't forget, any scripts that are actually used in other scripts via AddComponent wont get picked up by this.
     
  6. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    13,353
    Automation is key to this. That, and being organised up front.

    Learning how to write scripts for the Editor will boost your productivity by orders of magnitude in some cases. The other day I spend 45 seconds to write a script which automated a task people had been working on for around 15 minutes. The script got it done in one shot in under a second. While it wasn't relevant in that case, using a script to make bulk changes or whatnot also removes the possibility of human error and ensures consistency.
     
    Hunter_Bobeck and CarterG81 like this.
  7. hpjohn

    hpjohn

    Joined:
    Aug 14, 2012
    Posts:
    2,160
    I was thinking last night, you probably wouldn't want to check 1000 scripts one-by-one, so I put an option for checking all scripts in a project...
    then I was thinking about ways to find AddComponent(xxx) occurances...
    and then I was thinking about how to detect components in scenes that aren't prefabs
    ...and, well...
    it just got out of hand.

    Code (CSharp):
    1. //Assets/Editor/SearchForComponents.cs
    2. using UnityEngine;
    3. using UnityEditor;
    4. using System.Collections;
    5. using System.Collections.Generic;
    6.  
    7. public class SearchForComponents : EditorWindow {
    8.     [MenuItem( "EDITORS/Search For Components" )]
    9.     static void Init () {
    10.         SearchForComponents window = (SearchForComponents) EditorWindow.GetWindow( typeof( SearchForComponents ) );
    11.         window.Show();
    12.         window.position = new Rect( 20, 80, 550, 500 );
    13.     }
    14.  
    15.     string[] modes = new string[] { "Search for component usage", "Search for missing components" };
    16.     string[] checkType = new string[] { "Check single component", "Check all components" };
    17.  
    18.     List<string> listResult;
    19.     List<ComponentNames> prefabComponents,notUsedComponents, addedComponents, existingComponents, sceneComponents;
    20.     int editorMode, selectedCheckType;
    21.     MonoScript targetComponent;
    22.     string componentName = "";
    23.  
    24.     bool showPrefabs, showAdded, showScene, showUnused = true;
    25.     Vector2 scroll, scroll1, scroll2, scroll3, scroll4;
    26.  
    27.     class ComponentNames {
    28.         public string componentName;
    29.         public string namespaceName;
    30.         public string assetPath;
    31.         public List<string> usageSource;
    32.         public ComponentNames ( string comp, string space, string path ) {
    33.             this.componentName = comp;
    34.             this.namespaceName = space;
    35.             this.assetPath = path;
    36.             this.usageSource = new List<string>();
    37.         }
    38.         public override bool Equals ( object obj ) {
    39.             return ( (ComponentNames) obj ).componentName == componentName && ( (ComponentNames) obj ).namespaceName == namespaceName;
    40.         }
    41.         public override int GetHashCode () {
    42.             return componentName.GetHashCode() + namespaceName.GetHashCode();
    43.         }
    44.     }
    45.  
    46.     void OnGUI () {
    47.         GUILayout.Label(position+"");
    48.         GUILayout.Space( 3 );
    49.         int oldValue = GUI.skin.window.padding.bottom;
    50.         GUI.skin.window.padding.bottom = -20;
    51.         Rect windowRect = GUILayoutUtility.GetRect( 1, 17 );
    52.         windowRect.x += 4;
    53.         windowRect.width -= 7;
    54.         editorMode = GUI.SelectionGrid( windowRect, editorMode, modes, 2, "Window" );
    55.         GUI.skin.window.padding.bottom = oldValue;
    56.  
    57.         switch ( editorMode ) {
    58.             case 0:
    59.                 selectedCheckType = GUILayout.SelectionGrid( selectedCheckType, checkType, 2, "Toggle" );
    60.                 GUI.enabled = selectedCheckType == 0;
    61.                 targetComponent = (MonoScript) EditorGUILayout.ObjectField( targetComponent, typeof( MonoScript ), false );
    62.                 GUI.enabled = true;
    63.  
    64.                 if ( GUILayout.Button( "Check component usage" ) ) {
    65.                     AssetDatabase.SaveAssets();
    66.                     switch ( selectedCheckType ) {
    67.                         case 0:
    68.                             componentName = targetComponent.name;
    69.                             string targetPath = AssetDatabase.GetAssetPath( targetComponent );
    70.                             string[] allPrefabs = GetAllPrefabs();
    71.                             listResult = new List<string>();
    72.                             foreach ( string prefab in allPrefabs ) {
    73.                                 string[] single = new string[] { prefab };
    74.                                 string[] dependencies = AssetDatabase.GetDependencies( single );
    75.                                 foreach ( string dependedAsset in dependencies ) {
    76.                                     if ( dependedAsset == targetPath ) {
    77.                                         listResult.Add( prefab );
    78.                                     }
    79.                                 }
    80.                             }
    81.                             break;
    82.                         case 1:
    83.                             List<string> scenesToLoad = new List<string>();
    84.                             existingComponents = new List<ComponentNames>();
    85.                             prefabComponents = new List<ComponentNames>();
    86.                             notUsedComponents = new List<ComponentNames>();
    87.                             addedComponents = new List<ComponentNames>();
    88.                             sceneComponents = new List<ComponentNames>();
    89.  
    90.                             if ( EditorApplication.SaveCurrentSceneIfUserWantsTo() ) {
    91.                                 string projectPath = Application.dataPath;
    92.                                 projectPath = projectPath.Substring( 0, projectPath.IndexOf( "Assets" ) );
    93.  
    94.                                 string[] allAssets = AssetDatabase.GetAllAssetPaths();
    95.  
    96.                                 foreach ( string asset in allAssets ) {
    97.                                     int indexCS = asset.IndexOf( ".cs" );
    98.                                     int indexJS = asset.IndexOf( ".js" );
    99.                                     if ( indexCS != -1 || indexJS != -1 ) {
    100.                                         ComponentNames newComponent = new ComponentNames( NameFromPath( asset ), "", asset );
    101.                                         try {
    102.                                             System.IO.FileStream FS = new System.IO.FileStream( projectPath + asset, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.ReadWrite );
    103.                                             System.IO.StreamReader SR = new System.IO.StreamReader( FS );
    104.                                             string line;
    105.                                             while ( !SR.EndOfStream ) {
    106.                                                 line = SR.ReadLine();
    107.                                                 int index1 = line.IndexOf( "namespace" );
    108.                                                 int index2 = line.IndexOf( "{" );
    109.                                                 if ( index1 != -1 && index2 != -1 ) {
    110.                                                     line = line.Substring( index1 + 9 );
    111.                                                     index2 = line.IndexOf( "{" );
    112.                                                     line = line.Substring( 0, index2 );
    113.                                                     line = line.Replace( " ", "" );
    114.                                                     newComponent.namespaceName = line;
    115.                                                 }
    116.                                             }
    117.                                         } catch {
    118.                                         }
    119.  
    120.                                         existingComponents.Add( newComponent );
    121.  
    122.                                         try {
    123.                                             System.IO.FileStream FS = new System.IO.FileStream( projectPath + asset, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.ReadWrite );
    124.                                             System.IO.StreamReader SR = new System.IO.StreamReader( FS );
    125.  
    126.                                             string line;
    127.                                             int lineNum = 0;
    128.                                             while ( !SR.EndOfStream ) {
    129.                                                 lineNum++;
    130.                                                 line = SR.ReadLine();
    131.                                                 int index = line.IndexOf( "AddComponent" );
    132.                                                 if ( index != -1 ) {
    133.                                                     line = line.Substring( index + 12 );
    134.                                                     if ( line[0] == '(' ) {
    135.                                                         line = line.Substring( 1, line.IndexOf( ')' ) - 1 );
    136.                                                     } else if ( line[0] == '<' ) {
    137.                                                         line = line.Substring( 1, line.IndexOf( '>' ) - 1 );
    138.                                                     } else {
    139.                                                         continue;
    140.                                                     }
    141.                                                     line = line.Replace( " ", "" );
    142.                                                     line = line.Replace( "\"", "" );
    143.                                                     index = line.LastIndexOf( '.' );
    144.                                                     ComponentNames newComp;
    145.                                                     if ( index == -1 ) {
    146.                                                         newComp = new ComponentNames( line, "", "" );
    147.                                                     } else {
    148.                                                         newComp = new ComponentNames( line.Substring( index + 1, line.Length - ( index + 1 ) ), line.Substring( 0, index ), "" );
    149.                                                     }
    150.                                                     string pName = asset + ", Line " + lineNum;
    151.                                                     newComp.usageSource.Add( pName );
    152.                                                     index = addedComponents.IndexOf( newComp );
    153.                                                     if ( index == -1 ) {
    154.                                                         addedComponents.Add( newComp );
    155.                                                     } else {
    156.                                                         if ( !addedComponents[index].usageSource.Contains( pName ) ) addedComponents[index].usageSource.Add( pName );
    157.                                                     }
    158.                                                 }
    159.                                             }
    160.                                         } catch {
    161.                                         }
    162.                                     }
    163.                                     int indexPrefab = asset.IndexOf( ".prefab" );
    164.  
    165.                                     if ( indexPrefab != -1 ) {
    166.                                         string[] single = new string[] { asset };
    167.                                         string[] dependencies = AssetDatabase.GetDependencies( single );
    168.                                         foreach ( string dependedAsset in dependencies ) {
    169.                                             if ( dependedAsset.IndexOf( ".cs" ) != -1 || dependedAsset.IndexOf( ".js" ) != -1 ) {
    170.                                                 ComponentNames newComponent = new ComponentNames( NameFromPath( dependedAsset ), GetNamespaceFromPath( dependedAsset ), dependedAsset );
    171.                                                 int index = prefabComponents.IndexOf( newComponent );
    172.                                                 if ( index == -1 ) {
    173.                                                     newComponent.usageSource.Add( asset );
    174.                                                     prefabComponents.Add( newComponent );
    175.                                                 } else {
    176.                                                     if ( !prefabComponents[index].usageSource.Contains( asset ) ) prefabComponents[index].usageSource.Add( asset );
    177.                                                 }
    178.                                             }
    179.                                         }
    180.                                     }
    181.                                     int indexUnity = asset.IndexOf( ".unity" );
    182.                                     if ( indexUnity != -1 ) {
    183.                                         scenesToLoad.Add( asset );
    184.                                     }
    185.                                 }
    186.  
    187.                                 for ( int i = addedComponents.Count - 1; i > -1; i-- ) {
    188.                                     addedComponents[i].assetPath = GetPathFromNames( addedComponents[i].namespaceName, addedComponents[i].componentName );
    189.                                     if ( addedComponents[i].assetPath == "" ) addedComponents.RemoveAt( i );
    190.  
    191.                                 }
    192.  
    193.                                 foreach ( string scene in scenesToLoad ) {
    194.                                     EditorApplication.OpenScene( scene );
    195.                                     GameObject[] sceneGOs = GetAllObjectsInScene();
    196.                                     foreach ( GameObject g in sceneGOs ) {
    197.                                         Component[] comps = g.GetComponentsInChildren<Component>( true );
    198.                                         foreach ( Component c in comps ) {
    199.  
    200.                                             if ( c != null && c.GetType() != null && c.GetType().BaseType != null && c.GetType().BaseType == typeof( MonoBehaviour ) ) {
    201.                                                 SerializedObject so = new SerializedObject( c );
    202.                                                 SerializedProperty p = so.FindProperty( "m_Script" );
    203.                                                 string path = AssetDatabase.GetAssetPath( p.objectReferenceValue );
    204.                                                 ComponentNames newComp = new ComponentNames( NameFromPath( path ), GetNamespaceFromPath( path ), path );
    205.                                                 newComp.usageSource.Add( scene );
    206.                                                 int index = sceneComponents.IndexOf( newComp );
    207.                                                 if ( index == -1 ) {
    208.                                                     sceneComponents.Add( newComp );
    209.                                                 } else {
    210.                                                     if ( !sceneComponents[index].usageSource.Contains( scene ) ) sceneComponents[index].usageSource.Add( scene );
    211.                                                 }
    212.                                             }
    213.                                         }
    214.                                     }
    215.                                 }
    216.  
    217.                                 foreach ( ComponentNames c in existingComponents ) {
    218.                                     if ( addedComponents.Contains( c ) ) continue;
    219.                                     if ( prefabComponents.Contains( c ) ) continue;
    220.                                     if ( sceneComponents.Contains( c ) ) continue;
    221.                                     notUsedComponents.Add( c );
    222.                                 }
    223.  
    224.                                 addedComponents.Sort( SortAlphabetically );
    225.                                 prefabComponents.Sort( SortAlphabetically );
    226.                                 sceneComponents.Sort( SortAlphabetically );
    227.                                 notUsedComponents.Sort( SortAlphabetically );
    228.                             }
    229.                             break;
    230.                     }
    231.                 }
    232.                 break;
    233.             case 1:
    234.                 if ( GUILayout.Button( "Search!" ) ) {
    235.                     string[] allPrefabs = GetAllPrefabs();
    236.                     listResult = new List<string>();
    237.                     foreach ( string prefab in allPrefabs ) {
    238.                         UnityEngine.Object o = AssetDatabase.LoadMainAssetAtPath( prefab );
    239.                         GameObject go;
    240.                         try {
    241.                             go = (GameObject) o;
    242.                             Component[] components = go.GetComponentsInChildren<Component>( true );
    243.                             foreach ( Component c in components ) {
    244.                                 if ( c == null ) {
    245.                                     listResult.Add( prefab );
    246.                                 }
    247.                             }
    248.                         } catch {
    249.                             Debug.Log( "For some reason, prefab " + prefab + " won't cast to GameObject" );
    250.                         }
    251.                     }
    252.                 }
    253.                 break;
    254.         }
    255.         if ( editorMode == 1 || selectedCheckType == 0 ) {
    256.             if ( listResult != null ) {
    257.                 if ( listResult.Count == 0 ) {
    258.                     GUILayout.Label( editorMode == 0 ? ( componentName == "" ? "Choose a component" : "No prefabs use component " + componentName ) : ( "No prefabs have missing components!\nClick Search to check again" ) );
    259.                 } else {
    260.                     GUILayout.Label( editorMode == 0 ? ( "The following prefabs use component " + componentName + ":" ) : ( "The following prefabs have missing components:" ) );
    261.                     scroll = GUILayout.BeginScrollView( scroll );
    262.                     foreach ( string s in listResult ) {
    263.                         GUILayout.BeginHorizontal();
    264.                         GUILayout.Label( s, GUILayout.Width( position.width / 2 ) );
    265.                         if ( GUILayout.Button( "Select", GUILayout.Width( position.width / 2 - 10 ) ) ) {
    266.                             Selection.activeObject = AssetDatabase.LoadMainAssetAtPath( s );
    267.                         }
    268.                         GUILayout.EndHorizontal();
    269.                     }
    270.                     GUILayout.EndScrollView();
    271.                 }
    272.             }
    273.         } else {
    274.             showPrefabs = GUILayout.Toggle( showPrefabs, "Show prefab components" );
    275.             if ( showPrefabs ) {
    276.                 GUILayout.Label( "The following components are attatched to prefabs:" );
    277.                 DisplayResults( ref scroll1, ref prefabComponents );
    278.             }
    279.             showAdded = GUILayout.Toggle( showAdded, "Show AddComponent arguments" );
    280.             if ( showAdded ) {
    281.                 GUILayout.Label( "The following components are AddComponent arguments:" );
    282.                 DisplayResults( ref scroll2, ref addedComponents );
    283.             }
    284.             showScene = GUILayout.Toggle( showScene, "Show Scene-used components" );
    285.             if ( showScene ) {
    286.                 GUILayout.Label( "The following components are used by scene objects:" );
    287.                 DisplayResults( ref scroll3, ref sceneComponents );
    288.             }
    289.             showUnused = GUILayout.Toggle( showUnused, "Show Unused Components" );
    290.             if ( showUnused ) {
    291.                 GUILayout.Label( "The following components are not used by prefabs, by AddComponent, OR in any scene:" );
    292.                 DisplayResults( ref scroll4, ref notUsedComponents );
    293.             }
    294.         }
    295.     }
    296.  
    297.     int SortAlphabetically ( ComponentNames a, ComponentNames b ) {
    298.         return a.assetPath.CompareTo( b.assetPath );
    299.     }
    300.  
    301.     GameObject[] GetAllObjectsInScene () {
    302.         List<GameObject> objectsInScene = new List<GameObject>();
    303.         GameObject[] allGOs = (GameObject[]) Resources.FindObjectsOfTypeAll( typeof( GameObject ) );
    304.         foreach ( GameObject go in allGOs ) {
    305.             //if ( go.hideFlags == HideFlags.NotEditable || go.hideFlags == HideFlags.HideAndDontSave )
    306.             //    continue;
    307.  
    308.             string assetPath = AssetDatabase.GetAssetPath( go.transform.root.gameObject );
    309.             if ( !string.IsNullOrEmpty( assetPath ) )
    310.                 continue;
    311.  
    312.             objectsInScene.Add( go );
    313.         }
    314.  
    315.         return objectsInScene.ToArray();
    316.     }
    317.  
    318.     void DisplayResults ( ref Vector2 scroller, ref List<ComponentNames> list ) {
    319.         if ( list == null ) return;
    320.         scroller = GUILayout.BeginScrollView( scroller );
    321.         foreach ( ComponentNames c in list ) {
    322.             GUILayout.BeginHorizontal();
    323.             GUILayout.Label( c.assetPath, GUILayout.Width( position.width / 5 *4 ) );
    324.             if ( GUILayout.Button( "Select", GUILayout.Width( position.width / 5 - 30 ) ) ) {
    325.                 Selection.activeObject = AssetDatabase.LoadMainAssetAtPath( c.assetPath );
    326.             }
    327.             GUILayout.EndHorizontal();
    328.             if ( c.usageSource.Count == 1 ) {
    329.                 GUILayout.Label( "   In 1 Place: " + c.usageSource[0] );
    330.             }
    331.             if ( c.usageSource.Count > 1 ) {
    332.                 GUILayout.Label( "   In " + c.usageSource.Count + " Places: " + c.usageSource[0] + ", " + c.usageSource[1] + ( c.usageSource.Count > 2 ? ", ..." : "" ) );
    333.             }
    334.         }
    335.         GUILayout.EndScrollView();
    336.  
    337.     }
    338.  
    339.     string NameFromPath ( string s ) {
    340.         s = s.Substring( s.LastIndexOf( '/' ) + 1 );
    341.         return s.Substring( 0, s.Length - 3 );
    342.     }
    343.  
    344.     string GetNamespaceFromPath ( string path ) {
    345.         foreach ( ComponentNames c in existingComponents ) {
    346.             if ( c.assetPath == path ) {
    347.                 return c.namespaceName;
    348.             }
    349.         }
    350.         return "";
    351.     }
    352.  
    353.     string GetPathFromNames ( string space, string name ) {
    354.         ComponentNames test = new ComponentNames( name, space, "" );
    355.         int index = existingComponents.IndexOf( test );
    356.         if ( index != -1 ) {
    357.             return existingComponents[index].assetPath;
    358.         }
    359.         return "";
    360.     }
    361.  
    362.     public static string[] GetAllPrefabs () {
    363.         string[] temp = AssetDatabase.GetAllAssetPaths();
    364.         List<string> result = new List<string>();
    365.         foreach ( string s in temp ) {
    366.             if ( s.Contains( ".prefab" ) ) result.Add( s );
    367.         }
    368.         return result.ToArray();
    369.     }
    370. }
    371.  
    Theres a still a couple of ways a dependancy can slip through, if you have the following it wont catch it:
    Code (CSharp):
    1.     string componentName = "MyComponent";
    2.     gameObject.AddComponent( componentName );
    3.  
    And any scripts that arent really MonoBehaviours, eg scriptable objects or just classes; these will be picked up and listed as 'Unused'.
    I'm also not entirely sure how namespaces will affect it, but what I tested worked fine. (Win7 machine)

    Be aware, when you use the new option, it opens all the scenes in your prjoect to check the objects in them, so if you've got a lot of/large scenes, it might take a while to grind through them, but there's no infinate loops, so it's not crashing out, just give it a sec.
     
  8. GarthSmith

    GarthSmith

    Joined:
    Apr 26, 2012
    Posts:
    1,240
    @hpjohn Cool! I'll give this a go later today and let you know if I find any bugs. I feel like I can't be the first person dealing with a messy project and some other people might find this useful. Mind if I throw it on github or something?

    @angrypenguin You say automation is key, and that's one of the reasons we have so many prefabs now! lol I'm looking at 2D Toolkit and it seems to keep track of all it's own assets all the time. Whereas my editor code is being used to make-and-forget prefabs. We automated prefab creation, but we didn't automate clean-up! >.>
     
  9. AllanMSmith

    AllanMSmith

    Joined:
    Oct 2, 2012
    Posts:
    180
    wow this is almost a year old... but I just came here to say thank you for the script haha, very useful!
     
    CarterG81 and GarthSmith like this.
  10. sfjohansson

    sfjohansson

    Joined:
    Mar 12, 2013
    Posts:
    326
    Nice..thank you...was about to hook up localisations to spawned in game prefabs.. and I used this to find all my text prefabs...my hair will be eternally grateful! :)
     
    CarterG81 and GarthSmith like this.
  11. andrew_ES

    andrew_ES

    Joined:
    Apr 19, 2016
    Posts:
    9
    I just discovered this script and found it very helpful for the project I'm working on. I made one small addition to hpjohn's script which gives you the option to toggle between searching for the component/script in all dependencies or just direct dependencies.

    Thanks!

    Code (CSharp):
    1. //Assets/Editor/SearchForComponents.cs
    2. using UnityEngine;
    3. using UnityEditor;
    4. using System.Collections;
    5. using System.Collections.Generic;
    6.  
    7. public class SearchForComponents : EditorWindow
    8. {
    9.     [MenuItem( "Deadly Soap Tools/Search For Components" )]
    10.     static void Init ()
    11.     {
    12.         SearchForComponents window = (SearchForComponents) EditorWindow.GetWindow( typeof( SearchForComponents ) );
    13.         window.Show();
    14.         window.position = new Rect( 20, 80, 550, 500 );
    15.     }
    16.  
    17.     string[] modes = new string[] { "Search for component usage", "Search for missing components" };
    18.     string[] checkType = new string[] { "Check single component", "Check all components" };
    19.  
    20.     List<string> listResult;
    21.     List<ComponentNames> prefabComponents,notUsedComponents, addedComponents, existingComponents, sceneComponents;
    22.     int editorMode, selectedCheckType;
    23.     bool recursionVal;
    24.     MonoScript targetComponent;
    25.     string componentName = "";
    26.  
    27.     bool showPrefabs, showAdded, showScene, showUnused = true;
    28.     Vector2 scroll, scroll1, scroll2, scroll3, scroll4;
    29.  
    30.     class ComponentNames
    31.     {
    32.         public string componentName;
    33.         public string namespaceName;
    34.         public string assetPath;
    35.         public List<string> usageSource;
    36.         public ComponentNames ( string comp, string space, string path )
    37.         {
    38.             this.componentName = comp;
    39.             this.namespaceName = space;
    40.             this.assetPath = path;
    41.             this.usageSource = new List<string>();
    42.         }
    43.         public override bool Equals ( object obj )
    44.         {
    45.             return ( (ComponentNames) obj ).componentName == componentName && ( (ComponentNames) obj ).namespaceName == namespaceName;
    46.         }
    47.         public override int GetHashCode ()
    48.         {
    49.             return componentName.GetHashCode() + namespaceName.GetHashCode();
    50.         }
    51.     }
    52.  
    53.     void OnGUI ()
    54.     {
    55.         GUILayout.Label(position+"");
    56.         GUILayout.Space( 3 );
    57.         int oldValue = GUI.skin.window.padding.bottom;
    58.         GUI.skin.window.padding.bottom = -20;
    59.         Rect windowRect = GUILayoutUtility.GetRect( 1, 17 );
    60.         windowRect.x += 4;
    61.         windowRect.width -= 7;
    62.         editorMode = GUI.SelectionGrid( windowRect, editorMode, modes, 2, "Window" );
    63.         GUI.skin.window.padding.bottom = oldValue;
    64.  
    65.         switch ( editorMode )
    66.         {
    67.         case 0:
    68.             selectedCheckType = GUILayout.SelectionGrid (selectedCheckType, checkType, 2, "Toggle");
    69.             recursionVal = GUILayout.Toggle (recursionVal, "Search all dependencies");
    70.             GUI.enabled = selectedCheckType == 0;
    71.             targetComponent = (MonoScript) EditorGUILayout.ObjectField( targetComponent, typeof( MonoScript ), false );
    72.             GUI.enabled = true;
    73.  
    74.             if ( GUILayout.Button( "Check component usage" ) )
    75.             {
    76.                 AssetDatabase.SaveAssets();
    77.                 switch ( selectedCheckType )
    78.                 {
    79.                 case 0:
    80.                     componentName = targetComponent.name;
    81.                     string targetPath = AssetDatabase.GetAssetPath( targetComponent );
    82.                     string[] allPrefabs = GetAllPrefabs();
    83.                     listResult = new List<string>();
    84.                     foreach ( string prefab in allPrefabs )
    85.                     {
    86.                         string[] single = new string[] { prefab };
    87.                         string[] dependencies = AssetDatabase.GetDependencies( single, recursionVal );
    88.                         foreach ( string dependedAsset in dependencies )
    89.                         {
    90.                             if ( dependedAsset == targetPath )
    91.                             {
    92.                                 listResult.Add( prefab );
    93.                             }
    94.                         }
    95.                     }
    96.                     break;
    97.                 case 1:
    98.                     List<string> scenesToLoad = new List<string>();
    99.                     existingComponents = new List<ComponentNames>();
    100.                     prefabComponents = new List<ComponentNames>();
    101.                     notUsedComponents = new List<ComponentNames>();
    102.                     addedComponents = new List<ComponentNames>();
    103.                     sceneComponents = new List<ComponentNames>();
    104.  
    105.                     if ( EditorApplication.SaveCurrentSceneIfUserWantsTo() )
    106.                     {
    107.                         string projectPath = Application.dataPath;
    108.                         projectPath = projectPath.Substring( 0, projectPath.IndexOf( "Assets" ) );
    109.  
    110.                         string[] allAssets = AssetDatabase.GetAllAssetPaths();
    111.  
    112.                         foreach ( string asset in allAssets )
    113.                         {
    114.                             int indexCS = asset.IndexOf( ".cs" );
    115.                             int indexJS = asset.IndexOf( ".js" );
    116.                             if ( indexCS != -1 || indexJS != -1 )
    117.                             {
    118.                                 ComponentNames newComponent = new ComponentNames( NameFromPath( asset ), "", asset );
    119.                                 try
    120.                                 {
    121.                                     System.IO.FileStream FS = new System.IO.FileStream( projectPath + asset, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.ReadWrite );
    122.                                     System.IO.StreamReader SR = new System.IO.StreamReader( FS );
    123.                                     string line;
    124.                                     while ( !SR.EndOfStream )
    125.                                     {
    126.                                         line = SR.ReadLine();
    127.                                         int index1 = line.IndexOf( "namespace" );
    128.                                         int index2 = line.IndexOf( "{" );
    129.                                         if ( index1 != -1 && index2 != -1 )
    130.                                         {
    131.                                             line = line.Substring( index1 + 9 );
    132.                                             index2 = line.IndexOf( "{" );
    133.                                             line = line.Substring( 0, index2 );
    134.                                             line = line.Replace( " ", "" );
    135.                                             newComponent.namespaceName = line;
    136.                                         }
    137.                                     }
    138.                                 }
    139.                                 catch
    140.                                 {
    141.                                 }
    142.  
    143.                                 existingComponents.Add( newComponent );
    144.  
    145.                                 try
    146.                                 {
    147.                                     System.IO.FileStream FS = new System.IO.FileStream( projectPath + asset, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.ReadWrite );
    148.                                     System.IO.StreamReader SR = new System.IO.StreamReader( FS );
    149.  
    150.                                     string line;
    151.                                     int lineNum = 0;
    152.                                     while ( !SR.EndOfStream )
    153.                                     {
    154.                                         lineNum++;
    155.                                         line = SR.ReadLine();
    156.                                         int index = line.IndexOf( "AddComponent" );
    157.                                         if ( index != -1 )
    158.                                         {
    159.                                             line = line.Substring( index + 12 );
    160.                                             if ( line[0] == '(' )
    161.                                             {
    162.                                                 line = line.Substring( 1, line.IndexOf( ')' ) - 1 );
    163.                                             }
    164.                                             else if ( line[0] == '<' )
    165.                                             {
    166.                                                 line = line.Substring( 1, line.IndexOf( '>' ) - 1 );
    167.                                             }
    168.                                             else
    169.                                             {
    170.                                                 continue;
    171.                                             }
    172.                                             line = line.Replace( " ", "" );
    173.                                             line = line.Replace( "\"", "" );
    174.                                             index = line.LastIndexOf( '.' );
    175.                                             ComponentNames newComp;
    176.                                             if ( index == -1 )
    177.                                             {
    178.                                                 newComp = new ComponentNames( line, "", "" );
    179.                                             }
    180.                                             else
    181.                                             {
    182.                                                 newComp = new ComponentNames( line.Substring( index + 1, line.Length - ( index + 1 ) ), line.Substring( 0, index ), "" );
    183.                                             }
    184.                                             string pName = asset + ", Line " + lineNum;
    185.                                             newComp.usageSource.Add( pName );
    186.                                             index = addedComponents.IndexOf( newComp );
    187.                                             if ( index == -1 )
    188.                                             {
    189.                                                 addedComponents.Add( newComp );
    190.                                             }
    191.                                             else
    192.                                             {
    193.                                                 if ( !addedComponents[index].usageSource.Contains( pName ) ) addedComponents[index].usageSource.Add( pName );
    194.                                             }
    195.                                         }
    196.                                     }
    197.                                 }
    198.                                 catch
    199.                                 {
    200.                                 }
    201.                             }
    202.                             int indexPrefab = asset.IndexOf( ".prefab" );
    203.  
    204.                             if ( indexPrefab != -1 )
    205.                             {
    206.                                 string[] single = new string[] { asset };
    207.                                 string[] dependencies = AssetDatabase.GetDependencies( single, recursionVal );
    208.                                 foreach ( string dependedAsset in dependencies )
    209.                                 {
    210.                                     if ( dependedAsset.IndexOf( ".cs" ) != -1 || dependedAsset.IndexOf( ".js" ) != -1 )
    211.                                     {
    212.                                         ComponentNames newComponent = new ComponentNames( NameFromPath( dependedAsset ), GetNamespaceFromPath( dependedAsset ), dependedAsset );
    213.                                         int index = prefabComponents.IndexOf( newComponent );
    214.                                         if ( index == -1 )
    215.                                         {
    216.                                             newComponent.usageSource.Add( asset );
    217.                                             prefabComponents.Add( newComponent );
    218.                                         }
    219.                                         else
    220.                                         {
    221.                                             if ( !prefabComponents[index].usageSource.Contains( asset ) ) prefabComponents[index].usageSource.Add( asset );
    222.                                         }
    223.                                     }
    224.                                 }
    225.                             }
    226.                             int indexUnity = asset.IndexOf( ".unity" );
    227.                             if ( indexUnity != -1 )
    228.                             {
    229.                                 scenesToLoad.Add( asset );
    230.                             }
    231.                         }
    232.  
    233.                         for ( int i = addedComponents.Count - 1; i > -1; i-- )
    234.                         {
    235.                             addedComponents[i].assetPath = GetPathFromNames( addedComponents[i].namespaceName, addedComponents[i].componentName );
    236.                             if ( addedComponents[i].assetPath == "" ) addedComponents.RemoveAt( i );
    237.  
    238.                         }
    239.  
    240.                         foreach ( string scene in scenesToLoad )
    241.                         {
    242.                             EditorApplication.OpenScene( scene );
    243.                             GameObject[] sceneGOs = GetAllObjectsInScene();
    244.                             foreach ( GameObject g in sceneGOs )
    245.                             {
    246.                                 Component[] comps = g.GetComponentsInChildren<Component>( true );
    247.                                 foreach ( Component c in comps )
    248.                                 {
    249.  
    250.                                     if ( c != null && c.GetType() != null && c.GetType().BaseType != null && c.GetType().BaseType == typeof( MonoBehaviour ) )
    251.                                     {
    252.                                         SerializedObject so = new SerializedObject( c );
    253.                                         SerializedProperty p = so.FindProperty( "m_Script" );
    254.                                         string path = AssetDatabase.GetAssetPath( p.objectReferenceValue );
    255.                                         ComponentNames newComp = new ComponentNames( NameFromPath( path ), GetNamespaceFromPath( path ), path );
    256.                                         newComp.usageSource.Add( scene );
    257.                                         int index = sceneComponents.IndexOf( newComp );
    258.                                         if ( index == -1 )
    259.                                         {
    260.                                             sceneComponents.Add( newComp );
    261.                                         }
    262.                                         else
    263.                                         {
    264.                                             if ( !sceneComponents[index].usageSource.Contains( scene ) ) sceneComponents[index].usageSource.Add( scene );
    265.                                         }
    266.                                     }
    267.                                 }
    268.                             }
    269.                         }
    270.  
    271.                         foreach ( ComponentNames c in existingComponents )
    272.                         {
    273.                             if ( addedComponents.Contains( c ) ) continue;
    274.                             if ( prefabComponents.Contains( c ) ) continue;
    275.                             if ( sceneComponents.Contains( c ) ) continue;
    276.                             notUsedComponents.Add( c );
    277.                         }
    278.  
    279.                         addedComponents.Sort( SortAlphabetically );
    280.                         prefabComponents.Sort( SortAlphabetically );
    281.                         sceneComponents.Sort( SortAlphabetically );
    282.                         notUsedComponents.Sort( SortAlphabetically );
    283.                     }
    284.                     break;
    285.                 }
    286.             }
    287.             break;
    288.         case 1:
    289.             if ( GUILayout.Button( "Search!" ) )
    290.             {
    291.                 string[] allPrefabs = GetAllPrefabs();
    292.                 listResult = new List<string>();
    293.                 foreach ( string prefab in allPrefabs )
    294.                 {
    295.                     UnityEngine.Object o = AssetDatabase.LoadMainAssetAtPath( prefab );
    296.                     GameObject go;
    297.                     try
    298.                     {
    299.                         go = (GameObject) o;
    300.                         Component[] components = go.GetComponentsInChildren<Component>( true );
    301.                         foreach ( Component c in components )
    302.                         {
    303.                             if ( c == null )
    304.                             {
    305.                                 listResult.Add( prefab );
    306.                             }
    307.                         }
    308.                     }
    309.                     catch
    310.                     {
    311.                         Debug.Log( "For some reason, prefab " + prefab + " won't cast to GameObject" );
    312.                     }
    313.                 }
    314.             }
    315.             break;
    316.         }
    317.         if ( editorMode == 1 || selectedCheckType == 0 )
    318.         {
    319.             if ( listResult != null )
    320.             {
    321.                 if ( listResult.Count == 0 )
    322.                 {
    323.                     GUILayout.Label( editorMode == 0 ? ( componentName == "" ? "Choose a component" : "No prefabs use component " + componentName ) : ( "No prefabs have missing components!\nClick Search to check again" ) );
    324.                 }
    325.                 else
    326.                 {
    327.                     GUILayout.Label( editorMode == 0 ? ( "The following " + listResult.Count + " prefabs use component " + componentName + ":" ) : ( "The following prefabs have missing components:" ) );
    328.                     scroll = GUILayout.BeginScrollView( scroll );
    329.                     foreach ( string s in listResult )
    330.                     {
    331.                         GUILayout.BeginHorizontal();
    332.                         GUILayout.Label( s, GUILayout.Width( position.width / 2 ) );
    333.                         if ( GUILayout.Button( "Select", GUILayout.Width( position.width / 2 - 10 ) ) )
    334.                         {
    335.                             Selection.activeObject = AssetDatabase.LoadMainAssetAtPath( s );
    336.                         }
    337.                         GUILayout.EndHorizontal();
    338.                     }
    339.                     GUILayout.EndScrollView();
    340.                 }
    341.             }
    342.         }
    343.         else
    344.         {
    345.             showPrefabs = GUILayout.Toggle( showPrefabs, "Show prefab components" );
    346.             if ( showPrefabs )
    347.             {
    348.                 GUILayout.Label( "The following components are attatched to prefabs:" );
    349.                 DisplayResults( ref scroll1, ref prefabComponents );
    350.             }
    351.             showAdded = GUILayout.Toggle( showAdded, "Show AddComponent arguments" );
    352.             if ( showAdded )
    353.             {
    354.                 GUILayout.Label( "The following components are AddComponent arguments:" );
    355.                 DisplayResults( ref scroll2, ref addedComponents );
    356.             }
    357.             showScene = GUILayout.Toggle( showScene, "Show Scene-used components" );
    358.             if ( showScene )
    359.             {
    360.                 GUILayout.Label( "The following components are used by scene objects:" );
    361.                 DisplayResults( ref scroll3, ref sceneComponents );
    362.             }
    363.             showUnused = GUILayout.Toggle( showUnused, "Show Unused Components" );
    364.             if ( showUnused )
    365.             {
    366.                 GUILayout.Label( "The following components are not used by prefabs, by AddComponent, OR in any scene:" );
    367.                 DisplayResults( ref scroll4, ref notUsedComponents );
    368.             }
    369.         }
    370.     }
    371.  
    372.     int SortAlphabetically ( ComponentNames a, ComponentNames b )
    373.     {
    374.         return a.assetPath.CompareTo( b.assetPath );
    375.     }
    376.  
    377.     GameObject[] GetAllObjectsInScene ()
    378.     {
    379.         List<GameObject> objectsInScene = new List<GameObject>();
    380.         GameObject[] allGOs = (GameObject[]) Resources.FindObjectsOfTypeAll( typeof( GameObject ) );
    381.         foreach ( GameObject go in allGOs )
    382.         {
    383.             //if ( go.hideFlags == HideFlags.NotEditable || go.hideFlags == HideFlags.HideAndDontSave )
    384.             //    continue;
    385.  
    386.             string assetPath = AssetDatabase.GetAssetPath( go.transform.root.gameObject );
    387.             if ( !string.IsNullOrEmpty( assetPath ) )
    388.                 continue;
    389.  
    390.             objectsInScene.Add( go );
    391.         }
    392.  
    393.         return objectsInScene.ToArray();
    394.     }
    395.  
    396.     void DisplayResults ( ref Vector2 scroller, ref List<ComponentNames> list )
    397.     {
    398.         if ( list == null ) return;
    399.         scroller = GUILayout.BeginScrollView( scroller );
    400.         foreach ( ComponentNames c in list )
    401.         {
    402.             GUILayout.BeginHorizontal();
    403.             GUILayout.Label( c.assetPath, GUILayout.Width( position.width / 5 *4 ) );
    404.             if ( GUILayout.Button( "Select", GUILayout.Width( position.width / 5 - 30 ) ) )
    405.             {
    406.                 Selection.activeObject = AssetDatabase.LoadMainAssetAtPath( c.assetPath );
    407.             }
    408.             GUILayout.EndHorizontal();
    409.             if ( c.usageSource.Count == 1 )
    410.             {
    411.                 GUILayout.Label( "   In 1 Place: " + c.usageSource[0] );
    412.             }
    413.             if ( c.usageSource.Count > 1 )
    414.             {
    415.                 GUILayout.Label( "   In " + c.usageSource.Count + " Places: " + c.usageSource[0] + ", " + c.usageSource[1] + ( c.usageSource.Count > 2 ? ", ..." : "" ) );
    416.             }
    417.         }
    418.         GUILayout.EndScrollView();
    419.  
    420.     }
    421.  
    422.     string NameFromPath ( string s )
    423.     {
    424.         s = s.Substring( s.LastIndexOf( '/' ) + 1 );
    425.         return s.Substring( 0, s.Length - 3 );
    426.     }
    427.  
    428.     string GetNamespaceFromPath ( string path )
    429.     {
    430.         foreach ( ComponentNames c in existingComponents )
    431.         {
    432.             if ( c.assetPath == path )
    433.             {
    434.                 return c.namespaceName;
    435.             }
    436.         }
    437.         return "";
    438.     }
    439.  
    440.     string GetPathFromNames ( string space, string name )
    441.     {
    442.         ComponentNames test = new ComponentNames( name, space, "" );
    443.         int index = existingComponents.IndexOf( test );
    444.         if ( index != -1 )
    445.         {
    446.             return existingComponents[index].assetPath;
    447.         }
    448.         return "";
    449.     }
    450.  
    451.     public static string[] GetAllPrefabs ()
    452.     {
    453.         string[] temp = AssetDatabase.GetAllAssetPaths();
    454.         List<string> result = new List<string>();
    455.         foreach ( string s in temp )
    456.         {
    457.             if ( s.Contains( ".prefab" ) ) result.Add( s );
    458.         }
    459.         return result.ToArray();
    460.     }
    461. }
    462.  
     
  12. ifurkend

    ifurkend

    Joined:
    Sep 4, 2012
    Posts:
    350
    @hpjohn @andrew_ES How do I specify the class for standard component (e.g. mesh filter) instead of monoscript?
     
  13. bellicapax

    bellicapax

    Joined:
    Oct 5, 2016
    Posts:
    14
    Brilliant script. Upgraded it to work with my current unity (5.6.0f3)
     

    Attached Files:

  14. novaVision

    novaVision

    Joined:
    Nov 9, 2014
    Posts:
    372
    Is there a way to add "remove" all found components? I tried to modify it and call DestroyImmediate(component) but that didn't work
     
  15. Firlefanz73

    Firlefanz73

    Joined:
    Apr 2, 2015
    Posts:
    1,197
    Very helpful that SearchForComponents Script, thanks a lot :)
     
  16. millershaski

    millershaski

    Joined:
    Aug 22, 2013
    Posts:
    4
    There are a lot of great responses for finding missing components, but no one really talked about how to find all MonoBehaviours in your project.

    You can find MonoBehaviours on prefabs really easily. Once found, you can do whatever you want with them. You can select them in the editor, make changes to them, etc. I'm not sure if you can remove MonoBehaviours, maybe if you SetDirty(foundScript.gameObject)?


    Here's some example code:

    Code (CSharp):
    1.  
    2.  
    3.             MyScript[] allFoundScripts = Resources.FindObjectsOfTypeAll<MyScript>();
    4.          
    5.             foreach(MyScript foundScript in allFoundScripts)
    6.             {
    7.                 Debug.Log("Found the script in: " + foundScript.gameObject);
    8.              
    9.                 // Select the script in the inspector, if you want to
    10.                 UnityEditor.Selection.activeGameObject = foundScript.gameObject;
    11.  
    12.                 // You can also change variables on the found script
    13.                 foundScript.someVariable = 13;
    14.                 // Set dirty forces the inspector to save the change (there may be a better way to do this)
    15.                 UnityEditor.EditorUtility.SetDirty(foundScript);
    16.             }
     
    DoomGoober likes this.
  17. DoomGoober

    DoomGoober

    Joined:
    Dec 12, 2013
    Posts:
    7
    Building on @millershaski's answer, here's a simple EditorWindow for finding all prefabs that have the selected MonoBehaviour attached. Choose your MonoBehaviour and it will list all the prefabs that have it attached as buttons. Click the button and the Project View will select that prefab.

    Code (CSharp):
    1. using UnityEditor;
    2. using UnityEngine;
    3.  
    4. public class FindComponentUsagesWindow : EditorWindow
    5. {
    6.     private MonoScript targetMonoScript;
    7.     private Vector2 scrollPos;
    8.  
    9.     [MenuItem("Tools/Find Component Usages")]
    10.     public static void ShowWindow()
    11.     {
    12.         GetWindow<FindComponentUsagesWindow>(true, "Find Component Usages", true);
    13.     }
    14.  
    15.     void OnGUI()
    16.     {
    17.         targetMonoScript = (MonoScript)EditorGUILayout.ObjectField(targetMonoScript, typeof(MonoScript), false);
    18.         if (targetMonoScript != null)
    19.         {
    20.             scrollPos = EditorGUILayout.BeginScrollView(scrollPos);
    21.             System.Type targetType = targetMonoScript.GetClass();
    22.             if (targetType != null && targetType.IsSubclassOf(typeof(MonoBehaviour)))
    23.             {
    24.                 Object[] allMonoscriptsAsObjects = Resources.FindObjectsOfTypeAll(targetType);
    25.                 foreach (Object monoscriptAsObject in allMonoscriptsAsObjects)
    26.                 {
    27.                     GameObject prefab = ((MonoBehaviour)monoscriptAsObject).gameObject;
    28.                     if (GUILayout.Button(prefab.name))
    29.                     {
    30.                         Selection.activeObject = prefab;
    31.                     }
    32.                 }              
    33.             }
    34.             else
    35.             {
    36.                 EditorGUILayout.LabelField($"{targetMonoScript.name} is not a subclass of MonoBehavior");
    37.             }
    38.             EditorGUILayout.EndScrollView();
    39.         }
    40.     }
    41. }
     
  18. rmon222

    rmon222

    Joined:
    Oct 24, 2018
    Posts:
    71
  19. ArminRigo

    ArminRigo

    Joined:
    May 19, 2017
    Posts:
    8
    While we're at it, a throw-away script that locates all usages of the built-in Sphere mesh in all assets---simple enough to be quickly edited. If you have both the Console and the Project windows visible at the same time, clicking on each result in the Console highlights it in the Project window.

    Code (CSharp):
    1. using System.Linq;
    2. using UnityEditor;
    3. using UnityEngine;
    4.  
    5. public static class FindAllSpheres
    6. {
    7.     private const string MENU_ROOT = "Window/Where Are All Spheres";
    8.  
    9.     [MenuItem(MENU_ROOT)]
    10.     public static void _FindAllSpheres()
    11.     {
    12.         var go1 = GameObject.CreatePrimitive(PrimitiveType.Sphere);
    13.         var searchMesh = go1.GetComponent<MeshFilter>().sharedMesh;
    14.         Object.DestroyImmediate(go1);
    15.  
    16.         string[] pathsToAssets = AssetDatabase.FindAssets("t:GameObject");
    17.         Debug.Log("searching in " + pathsToAssets.Length + " gameobjects...");
    18.  
    19.         foreach (var path in pathsToAssets)
    20.         {
    21.             var path1 = AssetDatabase.GUIDToAssetPath(path);
    22.             var go = AssetDatabase.LoadAssetAtPath<GameObject>(path1);
    23.             if (go.GetComponentsInChildren<MeshFilter>().Any(mf => mf.sharedMesh == searchMesh))
    24.                 Debug.LogWarning("FOUND: " + path1, go);
    25.         }
    26.     }
    27. }
     
  20. JonPQ

    JonPQ

    Joined:
    Aug 10, 2016
    Posts:
    85
    Using DoomGoober's script above, I'd like to slightly modify it to find components, then on same gameObject... add another specified component.

    For example... I have a paramater
    MonoScript scrToAdd; //script to add to game object
    ...and a found 'prefab' with my target MonoScript type....
    how do I add 'scrToAdd' to the prefab please?....

    prefab.AddComponent<scrToAdd>(); //does not work
    prefab.AddComponent<typeof(scrToAdd)>(); //does not work

    but it works if I just type in a class as normal... e.g.
    prefab.AddComponent<TextMeshProUGUI>();

    how do I do this with a MonoScript paramater, or how do I cast MonoScript to something AddComponent understands please ?
     
    Last edited: Jan 11, 2021
  21. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    11,138
    Please don't reply to 7-year-old threads with unrelated questions.

    Just start your own new post... it's free!

    MonoScript looks like an Editor only class for manipulating NON-compiled script source code. I've certainly never had need to use MonoScript.

    You will NEVER be able to add non-compiled code to a GameObject.

    If you are looking for MonoBehaviour, that is the base class that all your scripts should derive from to be able to be used via AddComponent.
     
  22. JonPQ

    JonPQ

    Joined:
    Aug 10, 2016
    Posts:
    85
    Kurt, people have been replying to it in 2020, and my question is in reference to the script in this thread posted by doomGoober in may 2020, as I am looking at using a slightly modified version of the script here, so I can't post the question elsewhere as it wouldn't make much sense.

    That said. thanks for your reply.

    I'll answer my own question... the solution was to use the new PrefabUtility instead. It lets you loadAssetAtPath directly as a GameObject that you can add and remove components to/from. Then re save the prefab using
    PrefabUtility.ApplyPrefabInstance

    also an informative thread here... see https://forum.unity.com/threads/how-do-i-edit-prefabs-from-scripts.685711/
     
    Last edited: Jan 12, 2021
unityunity