If I click an object I can select its dependencies but I want to know the inverse of this. For example if I have texture how do I find all the objects that are using that texture.
This script will allow you to right click an object in the editor and will search your project and highlight the objects that reference it:
using UnityEngine;
using System.Collections;
using UnityEditor;
using System.Collections.Generic;
public class ReferenceFilter : EditorWindow
{
[MenuItem("Assets/What objects use this?", false, 20)]
private static void OnSearchForReferences()
{
string final = "";
List<UnityEngine.Object> matches = new List<UnityEngine.Object>();
int iid = Selection.activeInstanceID;
if (AssetDatabase.IsMainAsset(iid))
{
// only main assets have unique paths
string path = AssetDatabase.GetAssetPath(iid);
// strip down the name
final = System.IO.Path.GetFileNameWithoutExtension(path);
}
else
{
Debug.Log("Error Asset not found");
return;
}
// get everything
Object[] _Objects = FindObjectsOfTypeIncludingAssets(typeof(Object));
//loop through everything
foreach (Object go in _Objects)
{
// needs to be an array
Object[] g = new Object[1];
g[0] = go;
// All objects
Object[] depndencies = EditorUtility.CollectDependencies(g);
foreach (Object o in depndencies)
if (string.Compare(o.name.ToString(), final) == 0)
matches.Add(go);// add it to our list to highlight
}
Selection.objects = matches.ToArray();
matches.Clear(); // clear the list
}
}
You will need to place it in an editor folder for this to work.
For example if I have texture how do I find all the objects that are using that texture.
There is a product which allows you to search for usages (inverse to dependencies) in both Project and Scenes, e.g. it offers:
- Interface for working with exact fields that are using selected asset
- Search for usages of different asset types: Textures, Scenes, Scripts, Shaders, Materials, Sprites, Prefabs, Sounds…
- Replacement of asset usages
Asset Store link:
This will work for all loaded objects (Not Assets in the Project):
using System;
using System.Reflection;
using UnityEditor;
using UnityEngine;
public class BacktraceReference : EditorWindow {
private Class1 _theObject;
[MenuItem("GameObject/What Objects Reference this?")]
public static void Init() {
GetWindow(typeof (BacktraceReference));
}
public void OnGUI() {
_theObject = EditorGUILayout.ObjectField("Object referenced : ", _theObject, typeof (Class1), true) as Class1;
if (_theObject == null) return;
if (GUILayout.Button("Find Objects Referencing it"))
FindObjectsReferencing(_theObject);
}
private static void FindObjectsReferencing<T>(T mb) where T : Component {
var objs = Resources.FindObjectsOfTypeAll(typeof (Component)) as Component[];
if (objs == null) return;
foreach (Component obj in objs) {
FieldInfo[] fields =
obj.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance |
BindingFlags.Static);
foreach (FieldInfo fieldInfo in fields) {
if (FieldReferencesComponent(obj, fieldInfo, mb)) {
Debug.Log("Ref: Component " + obj.GetType() + " from Object " + obj.name);
}
}
}
}
private static bool FieldReferencesComponent<T>(Component obj, FieldInfo fieldInfo, T mb) where T : Component {
if (fieldInfo.FieldType.IsArray) {
var arr = fieldInfo.GetValue(obj) as Array;
foreach (object elem in arr) {
if (elem.GetType() == mb.GetType()) {
var o = elem as T;
if (o == mb)
return true;
}
}
}
else {
if (fieldInfo.FieldType == mb.GetType()) {
var o = fieldInfo.GetValue(obj) as T;
if (o == mb)
return true;
}
}
return false;
}
}
I hacked together a version of @ricardo_arango’s script which works in Unity 5.4 and has some additional functionality (optionally find references to any component in any currently-selected GameObjects, and highlight the referencing GameObject when you click the related log entry).
I realise it’s not an elegant solution, but it works and I don’t have time for elegance right now, so posting in case someone else finds a use for it. Tried to post it as a comment to his answer but it wouldn’t submit for some reason.
using System;
using System.Reflection;
using UnityEditor;
using UnityEngine;
public class BacktraceReference : EditorWindow {
private Component _theObject;
bool specificComponent = false;
[MenuItem("GameObject/What Objects Reference this?")]
public static void Init() {
GetWindow(typeof (BacktraceReference));
}
public void OnGUI() {
if( specificComponent = GUILayout.Toggle(specificComponent, "Match a single specific component") ) {
_theObject = EditorGUILayout.ObjectField("Component referenced : ", _theObject, typeof(Component), true) as Component;
if( _theObject == null )
return;
if( GUILayout.Button("Find Objects Referencing it") )
FindObjectsReferencing(_theObject);
}
else if( GUILayout.Button("Find Objects Referencing Selected GameObjects") )
{
GameObject[] objects = Selection.gameObjects;
if( objects==null || objects.Length < 1 ) {
GUILayout.Label("Select source object/s in Hierarchy.");
return;
}
foreach( GameObject go in objects ) {
foreach( Component c in go.GetComponents(typeof(Component)) ) {
FindObjectsReferencing(c);
}
}
}
}
private static void FindObjectsReferencing<T>(T mb) where T : Component {
var objs = Resources.FindObjectsOfTypeAll(typeof (Component)) as Component[];
if (objs == null) return;
foreach (Component obj in objs) {
FieldInfo[] fields =
obj.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance |
BindingFlags.Static);
foreach (FieldInfo fieldInfo in fields) {
if (FieldReferencesComponent(obj, fieldInfo, mb)) {
Debug.Log("Ref: Component " + obj.GetType() + " from Object " + obj.name +" references source component "+mb.GetType(), obj.gameObject);
}
}
}
}
private static bool FieldReferencesComponent<T>(Component obj, FieldInfo fieldInfo, T mb) where T : Component {
if (fieldInfo.FieldType.IsArray) {
var arr = fieldInfo.GetValue(obj) as Array;
foreach (object elem in arr) {
if (elem != null && mb != null && elem.GetType() == mb.GetType()) {
var o = elem as T;
if (o == mb)
return true;
}
}
}
else {
if (fieldInfo.FieldType == mb.GetType()) {
var o = fieldInfo.GetValue(obj) as T;
if (o == mb)
return true;
}
}
return false;
}
}
I made a script with similar functionality to @Daniel-F. It only handles a single scene file. Yet it handles all type of sub-references well, complex objects, arrays, etc… Tested in 2013.3.1f1 & 5.6.3f1
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
#if UNITY_EDITOR
using UnityEditor;
public class BacktraceReference : EditorWindow
{
/// <summary> The result </summary>
public static List<Component> ReferencingSelection = new List<Component>();
/// <summary> allComponents in the scene that will be searched to see if they contain the reference </summary>
private static Component[] allComponents;
/// <summary> Selection of gameobjects the user made </summary>
private static GameObject[] selections;
/// <summary>
/// Adds context menu to hierarchy window https://answers.unity.com/questions/22947/adding-to-the-context-menu-of-the-hierarchy-tab.html
/// </summary>
[UnityEditor.MenuItem("GameObject/Find Objects Referencing This", false, 48)]
public static void InitHierarchy()
{
selections = UnityEditor.Selection.gameObjects;
BacktraceSelection(selections);
GetWindow(typeof(BacktraceReference));
}
/// <summary>
/// Display referenced by components in window
/// </summary>
public void OnGUI()
{
if (selections == null || selections.Length < 1)
{
GUILayout.Label("Select source object/s from scene Hierarchy panel.");
return;
}
// display reference that is being checked
GUILayout.Label(string.Join(", ", selections.Where(go => go != null).Select(go => go.name).ToArray()));
// handle no references
if (ReferencingSelection == null || ReferencingSelection.Count == 0)
{
GUILayout.Label("is not referenced by any gameobjects in the scene");
return;
}
// display list of references using their component name as the label
foreach (var item in ReferencingSelection)
{
EditorGUILayout.ObjectField(item.GetType().ToString(), item, typeof(GameObject), allowSceneObjects: true);
}
}
// This script finds all objects in scene
private static Component[] GetAllActiveInScene()
{
// Use new version of Resources.FindObjectsOfTypeAll(typeof(Component)) as per https://forum.unity.com/threads/editorscript-how-to-get-all-gameobjects-in-scene.224524/
var rootObjects = UnityEngine.SceneManagement.SceneManager
.GetActiveScene()
.GetRootGameObjects();
List<Component> result = new List<Component>();
foreach (var rootObject in rootObjects)
{
result.AddRange(rootObject.GetComponentsInChildren<Component>());
}
return result.ToArray();
}
private static void BacktraceSelection(GameObject[] selections)
{
if (selections == null || selections.Length < 1)
return;
allComponents = GetAllActiveInScene();
if (allComponents == null) return;
ReferencingSelection.Clear();
foreach (GameObject selection in selections)
{
foreach (Component cOfSelection in selection.GetComponents(typeof(Component)))
{
FindObjectsReferencing(cOfSelection);
}
}
}
private static void FindObjectsReferencing<T>(T cOfSelection) where T : Component
{
foreach (Component sceneComponent in allComponents)
{
componentReferences(sceneComponent, cOfSelection);
}
}
/// <summary>
/// Determines if the component makes any references to the second "references" component in any of its inspector fields
/// </summary>
private static void componentReferences(Component component, Component references)
{
// find all fields exposed in the editor as per https://answers.unity.com/questions/1333022/how-to-get-every-public-variables-from-a-script-in.html
SerializedObject serObj = new SerializedObject(component);
SerializedProperty prop = serObj.GetIterator();
while (prop.NextVisible(true))
{
bool isObjectField = prop.propertyType == SerializedPropertyType.ObjectReference && prop.objectReferenceValue != null;
if (isObjectField && prop.objectReferenceValue == references)
{
ReferencingSelection.Add(component);
}
}
}
}
#endif
@tnetennba You may want to check out Find Reference 2, it shows the usage count and all references from and to any selected object in project panel
To additionally find references to the object in unloaded scenes or assets, you could search the text of your .unity and .prefab files for the target object’s guid.
Get the guid:
string guid = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(Selection.activeObject));
Use some C# code to search files recursively in Application.dataPath, and you should get a list of files that reference the guid. You may want to strip .meta
from the results since a prefab’s own meta file will contain its prefab.
As an optimization, you should ignore binary files. (So you’re not searching textures.)
Alternatively, unity-findrefs is a simple unity package for finding references. It shows the results in the console:
It depends on ripgrep or mdfind for fast searching instead of implementing it in C#.
Hi !
Check out this open source tool, it is perfect for finding dependencies of an asset and what references it.
Have fun !
There is yet another tool for that: GitHub - AlexeyPerov/Unity-Dependencies-Hunter: This tool finds unreferenced assets by scanning all files in your Unity project..
It consists of a single script so it’s easy to just copy-paste it to your project.
Internally it uses AssetDatabase.GetDependencies to build a map of all assets to use for analysis.