How can I see script dependencies?

I've recently joined a project as a coder and most of the scripts are in the Scripts folder. Sometimes I come across scripts that have duplicates and I want to delete one of them, but I cant figure out how I can see WHERE that script is beeing used. Other objects in Unity have the action "Select dependencies", but this doesnt seem to work for Scripts.

AngryAnt has a great script on his site that does the trick:

http://angryant.com/2009/08/31/where-did-that-component-go/

I'm pretty sure this is not possible. My reasoning for this is that all scripts are included at runtime, and therefore all scripts are potentially available as types which could potentially be instantiated at runtime. In order for the editor to know whether any particular scripts are used or not, it would have to be able to somehow parse every possible runtime permutation of your code.

consider:

gameObject.AddComponent ("FoobarScript_" + Random.Range(a,b).ToString());

The editor would have to work out every potential value for a & b, before knowing which scripts might potentially be called on! :)

This should be possible with editor scripting - but I think it's not trivial:

You'd have to go through all your scenes. Among other things, you'd use EditorApplication.OpenScene to do this. In the scenes, you should be able to use Object.FindObjectsOfType with the type you're looking for, to get all game objects that have the script you're looking for attached (actually, you get the components - but from there you can easily get the actual game object; and the hierarchy of the game objects is stored in the "transform" attribute of the components which the inherit from Component).

You should be able to select those objects with Selection.gameObjects - but since you're iterating through the scenes that won't help you much, so it's probably better to simply log the names of the game objects and maybe iterate through their transform.parent to get the full path. I haven't tried setting Selection.gameObjects - but the scripting reference doesn't say it's read-only so that should work (if you want to just do this for a single scene, that sure would be nice).

Finally, you'd have to check out all the prefabs in the project. One approach might be simple iterating through the file structure (that could be done with standard .NET API calls - DirectoryInfo.GetDirectories is one of the methods you'd be using for that) and then using AssetDatabase.LoadAssetAtPath to get "living instances" of any prefab and then checking if those contain the script you're looking for (via GetComponent - if it doesn't return null for the given type, the script is used).

I'm not sure this will all work (and you'll probably need a bit more than what I've linked here), and when it works (which I would hope) it'll be a bit of work to implement this - but it's certainly worth a try and would be a great example of the power of editor scripting ;-)

In my Unity 3.2 it gave some errors when switching Scenes while the Window was open. Plus I wanted to search the component quickly so I have added sorting to the components and the GameObjects it's attached to. Furthermore I rendered the script component in a different color so you could quickly identify them. I also added auto Refresh, filter on name and filter on script components. This is my first EditorWindow script modification try and my first C# Unity thingy. Original idea and code by AngryAnt.

Here's the fixed and modified script:

using UnityEngine;
using UnityEditor;
using System.Collections; 

public class ComponentLister : EditorWindow
{
    bool forceRefresh=false;

    private bool onlyScripts=false;
    private string filterComponent="";
    private SortedList sets = new SortedList(new myReverserClass());
    private ArrayList scripts = new ArrayList();
    private Vector2 scrollPosition;

   public class myReverserClass : IComparer  {

      // Calls CaseInsensitiveComparer.Compare with the parameters reversed.
      public int Compare( System.Object x, System.Object y )  {
          return ( (new CaseInsensitiveComparer()).Compare( ((System.Type)x).Name, ((System.Type)y).Name ) );
      }
   }

    [ MenuItem( "Component/Component lister" ) ]
    public static void Launch()
    {
        ComponentLister window = (ComponentLister)GetWindow( typeof( ComponentLister ) );
        window.forceRefresh=true;
        window.Show();
    } 

    public void UpdateList()
    {
        Object[] objects; 

        sets.Clear(); 
        scripts.Clear();

        objects = FindObjectsOfType( typeof( Component ) );
        foreach( Component component in objects )
        {
            if (component is MonoBehaviour) {
                //Debug.Log(component.GetType() + " attached to "+component.name);
                scripts.Add(component.GetType());
            }

            if( !sets.ContainsKey( component.GetType() ) )
            {
                sets.Add(component.GetType(),new ArrayList());
            } 
            int i=sets.IndexOfKey(component.GetType());
            ( ( ArrayList )sets.GetByIndex(i)).Add( (string)component.gameObject.name );
        }

        foreach( Component component in objects )
        {
            int i=sets.IndexOfKey(component.GetType());
            ( ( ArrayList )sets.GetByIndex(i)).Sort();
        }       

    } 

    public void OnHierarchyChange() {
        //Debug.Log("OnHierarchyChange");
        UpdateList();
        Repaint();
        forceRefresh = true;
    }

    public void OnGUI()
    {
        GUILayout.BeginHorizontal( GUI.skin.GetStyle( "Box" ) );
            GUILayout.Label( "Components in scene:" );

            GUILayout.FlexibleSpace();

            if( GUILayout.Button( "Refresh" ) || forceRefresh )
            {
                //if (forceRefresh) Debug.Log("forceRefresh");
                forceRefresh=false;
                UpdateList();

            }
        GUILayout.EndHorizontal();

        GUILayout.BeginHorizontal( GUI.skin.GetStyle( "Box" ) );
        filterComponent = EditorGUILayout.TextField ("Filter:", filterComponent);
        GUILayout.EndHorizontal();

        GUILayout.BeginHorizontal( GUI.skin.GetStyle( "Box" ) );
        onlyScripts = EditorGUILayout.Toggle("Show only scripts", onlyScripts);
        GUILayout.EndHorizontal();

        scrollPosition = GUILayout.BeginScrollView(scrollPosition);

            foreach( System.Type type in sets.Keys )
            {   
                if (type.Name.ToLower().Contains(filterComponent.ToLower())) {
                    bool showGameObjects=false;
                    if (scripts.Contains(type)) {
                        GUI.contentColor = Color.yellow;
                        GUILayout.Label( type.Name + " (Script):" );
                        showGameObjects=true;
                    }
                    else if (!onlyScripts){
                        GUI.contentColor = Color.white;
                        GUILayout.Label( type.Name + ":" );
                        showGameObjects=true;
                    }

                    if (showGameObjects) {
                        GUI.contentColor = Color.white;
                        foreach( string gameObject in ( ArrayList )sets[ type ] )
                        {
                            if( GUILayout.Button( gameObject ) )
                            {
                                Selection.activeObject = GameObject.Find(gameObject);
                            }
                        }
                    }
                }
            } 

        GUILayout.EndScrollView();
    }
}

I'm sorry if I didn't phrase my question correctly, and that it was unclear. Since scripts are added to gameobjects using the unity inspector, I was merely looking for a way to see which gameobjects a certain script had been added to. Now I have to go through every gameobject by hand in the hierarchy or look at prefabs in the Project that I think has some relation to the script and see if they have been added to it.

I tried a little improvement of Angry Ant’s script.
Basically all component are sorted and you can fold/unfold them for better readibility.

I did it during my student project (also my first Unity project). And now that the project is over, I’m happy to share it with the commmunity.

using UnityEngine;
using UnityEditor;
using System.Collections;
using System.Collections.Generic;

/**
 * \author Nicolas Musset, Angry Ant (original version)
 * \date 2011-03-28
 * \class ComponentLister
 * \brief This class adds a window in the Unity editor that lists all
 *  components used in the current scene.
 */
public class ComponentLister : EditorWindow
{
    private SortedList<string, ArrayList> sets =
		new SortedList<string, ArrayList>();
    private SortedList<string, bool> foldedOuts =
		new SortedList<string, bool>();
    private Vector2 scrollPosition;

    /**
     * Menu entry for this window
     */
    [MenuItem("Component/Component Lister", priority = 41)]
    public static void MenuComponentLister()
    {
        EditorWindow window = GetWindow(typeof(ComponentLister));
        window.Show();
    }

    /**
     * Updates the list of components
     */
    public void UpdateList()
    {
        Object[] objects;
        objects = FindObjectsOfType(typeof(Component));

        sets.Clear();
        sets.Capacity = objects.Length;
        foldedOuts.Clear();
        foldedOuts.Capacity = objects.Length;

        foreach (Component component in objects)
        {
            string name = component.GetType().Name;
            if (!sets.ContainsKey(name))
            {
                sets[name] = new ArrayList();
                foldedOuts[name] = false;
            }

            (sets[name]).Add(component.gameObject);
        }
    }

    /**
     * Updates the list each time the hierarchy has been changed.
     * This also work when the scene is changed.
     */
    public void OnHierarchyChange()
    {
        UpdateList();
        Repaint();
    }
    
    /**
     * Override.
     */
    public void OnGUI()
    {
        GUILayout.BeginHorizontal(GUI.skin.GetStyle("Box"));
        GUILayout.Label("Components in scene:");
        GUILayout.FlexibleSpace();

        if (GUILayout.Button("Refresh"))
        {
            UpdateList();
        }
        GUILayout.EndHorizontal();

        scrollPosition = GUILayout.BeginScrollView(scrollPosition);
        
        foreach (string name in sets.Keys)
        {
            foldedOuts[name] =
				EditorGUILayout.Foldout(foldedOuts[name], name,
				                        new GUIStyle(EditorStyles.foldout)
				                        { fontStyle = FontStyle.Bold });
            if (foldedOuts[name])
            {
                foreach (GameObject gameObject in sets[name])
                {
                    if (GUILayout.Button(gameObject.name))
                    {
                        Selection.activeObject = gameObject;
                    }
                }
            }
        }

        GUILayout.EndScrollView();
    }
}

The solutions shared here are a lot more useful, but you can also right click any script and select “Find References in Scene” to show game objects in the hierarchy for the current scene that have have the script attached as a component.

“Select dependencies” shows no results when you run it on a script, because scripts don’t depend on any other objects.

When you add a component of the script’s type to a GameObject, then there’s a dependency from that component to your script, not the other way around. When you context-click the script in the project view, you can choose “Find references in scene”. That will select the scene objects which depend on your script.

If you want to see the complete dependency paths and include all scenes, try this plugin for RelationsInspector. You can see it in action here.