As a request that had came in through the support channel someone asked if this would be possible. So I set about writing this lovely little script:
using System.Linq;
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
public class ReferenceFilter : EditorWindow
{
private static ReferenceFilter _referenceFilter;
public static Object Sel = Selection.activeObject;
static readonly List<Object> Matches = new List<Object>();
static readonly List<Object> SceneList = new List<Object>();
static readonly List<Object> InCurrentScene = new List<Object>();
bool _objectFoldout = false;
bool _sceneFoldout = false;
private bool _projectFoldout = false;
private static bool _noReferencesFound = false;
[MenuItem("Unity Support Tools/Project/What objects use this?")]
private static void LaunchReferenceFilterWindow()
{
// make sure the scene files are available to search
PreLoadScenes();
_referenceFilter = GetWindow<ReferenceFilter>();
}
private static void ClearResults()
{
Matches.Clear();
InCurrentScene.Clear();
SceneList.Clear();
_noReferencesFound = false;
}
private static bool AreListsEmpty()
{
return Matches.Count + InCurrentScene.Count + SceneList.Count == 0;
}
void OnGUI()
{
if (GUILayout.Button("Search"))
OnSearchForReferences();
if (GUILayout.Button("Clear Search Results"))
ClearResults();
Sel = EditorGUILayout.ObjectField("Selection", Sel, typeof(Object), false, GUILayout.ExpandWidth(true));
// avoids null reference exception spam
string selectionName = Sel != null ? Sel.name : "";
_objectFoldout = EditorGUILayout.Foldout(_objectFoldout, "Objects in the current scene referencing " + selectionName);
if (_objectFoldout)
{
EditorGUIUtility.LookLikeControls(0, _referenceFilter.position.width);
foreach (var match in Matches)
EditorGUILayout.ObjectField("", match, typeof(Object), false, GUILayout.ExpandWidth(true));
}
_projectFoldout = EditorGUILayout.Foldout(_projectFoldout, "Objects in Project that reference " + selectionName);
if (_projectFoldout)
{
EditorGUIUtility.LookLikeControls(0, _referenceFilter.position.width);
foreach (var match in InCurrentScene)
EditorGUILayout.ObjectField("", match, typeof(Object), false, GUILayout.ExpandWidth(true));
}
_sceneFoldout = EditorGUILayout.Foldout(_sceneFoldout, "Scenes that contain objects referencing " + selectionName);
if (_sceneFoldout)
{
EditorGUIUtility.LookLikeControls(0, _referenceFilter.position.width);
foreach (var scene in SceneList)
EditorGUILayout.ObjectField("", scene, typeof(Object), false, GUILayout.ExpandWidth(true));
}
if (_noReferencesFound)
EditorGUILayout.LabelField("", selectionName + " is not referenced by anything in this project");
Repaint();
}
void Update()
{
Repaint();
}
static void PreLoadScenes()
{
// we need to find the scene files and select them so that they will appear in the AssetDatabase
// unity will only add the scene to the assetdatabase once it has been clicked on
var files = System.IO.Directory.GetFiles(Application.dataPath, "*.unity", System.IO.SearchOption.AllDirectories);
var l = Application.dataPath.Length;
foreach (var s in files)
{
string temp = s.Remove(0, l);
temp = temp.Insert(0, "Assets");
temp = temp.Replace("\\", "/");
AssetDatabase.LoadAssetAtPath(temp, typeof(Object));
}
}
private static bool GetCurrentSelection(out string _object)
{
if (AssetDatabase.Contains(Sel))
{
int iid = Sel.GetInstanceID();
if (AssetDatabase.IsMainAsset(iid))
{
_object = System.IO.Path.GetFileNameWithoutExtension(AssetDatabase.GetAssetPath(iid));
return true;
}
}
_object = "";
return false;
}
private static string GetCurrentScene()
{
return System.IO.Path.GetFileNameWithoutExtension(EditorApplication.currentScene);
}
private static void AddReferencesToList(Object _currentObject, string _ref, Object[] _dependencyList, List<Object> _listToAddTo)
{
foreach (Object dependency in _dependencyList)
if (string.Compare(dependency.name, _ref) == 0 string.Compare(dependency.name , "HandlesGO") != 0)
{
// check for game objects and dont include child objects as they generate duplicates for each component
var gameobject = _currentObject as GameObject;
if (gameobject != null gameobject.transform.parent == null gameobject != Selection.activeObject !Matches.Contains(_currentObject))
_listToAddTo.Add(_currentObject); // add it to our list to highlight
//add scene files(DefaultAsset)
if (_currentObject.ToString().Contains("DefaultAsset") !SceneList.Contains(_currentObject))
SceneList.Add(_currentObject);
// check for materials as they are not game objects
var mat = _currentObject as Material;
if (mat != null mat != Selection.activeObject)
_listToAddTo.Add(_currentObject); // add it to our list to highlight
}
}
private static void OnSearchForReferences()
{
// make sure scene files that have been added since the window was luanched are included
PreLoadScenes();
ClearResults();
string final;
bool cancel = false;
if (!GetCurrentSelection(out final))
{
Debug.Log("Asset is not contained in the AssetDatabase. It is likely that this object is only present in the current scene");
return;
}
// get everything
Object[] allObjects = Resources.FindObjectsOfTypeAll(typeof(Object));
var noOfObjects = allObjects.Length;
var searchedSoFar = 0;
//loop through everything
foreach (Object obj in allObjects)
{
// hack fix
if (obj.name == "HandlesGO") continue;
// All objects
Object[] dependencies = EditorUtility.CollectDependencies(new[] { obj });
AddReferencesToList(obj, final, dependencies, Matches);
// progress bar logic
searchedSoFar++;
cancel = EditorUtility.DisplayCancelableProgressBar("Searching all references", "Completed: " + ((searchedSoFar / (float)noOfObjects))*100.0f + "%" ,searchedSoFar/(float) noOfObjects);
if (cancel)
{
ClearResults();
_noReferencesFound = true;
EditorUtility.ClearProgressBar();
return;
}
}
searchedSoFar = 0;
foreach (var scene in SceneList)
{
noOfObjects = SceneList.Count;
//get the objects that are scene dependencies
Object[] dependencies = EditorUtility.CollectDependencies(new[] { scene });
foreach (var dependency in dependencies.Where(dependency => Matches.Contains(dependency)))
{
InCurrentScene.Add(dependency);
Matches.Remove(dependency);
}
EditorUtility.DisplayProgressBar("Gathering referenced scenes", "Completed: " + ((searchedSoFar / (float)noOfObjects)) * 100.0f + "%", searchedSoFar / (float)noOfObjects);
}
Selection.objects = Matches.ToArray();
EditorUtility.ClearProgressBar();
_noReferencesFound = AreListsEmpty();
}
}
This is an Editor script so you will need to remember to put it into and Editor folder in your project window.
To use it simply right click any object in your project tab and it will search everything in your project and your scenes and highlight it for you.
I will try and give it a bit more ZAZZ at some point but for now the basic functionality is on there.
I should add any input on this is more welcome, I’m sure someone will come along and tell me that there is an even better way to do it. any changes that are made I will try and keep this first post updated with them.
If you find this useful please up vote it on answers: