Commit 1
This commit is contained in:
161
Assets/Editor/ReferenceFinderTool.cs
Normal file
161
Assets/Editor/ReferenceFinderTool.cs
Normal file
@@ -0,0 +1,161 @@
|
||||
// ===============================================================================
|
||||
// ReferenceFinderTool - Deep Dependency Analysis for Unity Assets
|
||||
//
|
||||
// Creator: Scove
|
||||
// Last Updated: 2024-05-08
|
||||
// Version: 2.0
|
||||
//
|
||||
// Purpose:
|
||||
// Finds every asset in the project that references the selected item by
|
||||
// scanning GUIDs inside Unity's YAML-based files (Scenes, Prefabs, Materials, etc.).
|
||||
//
|
||||
// Key Features:
|
||||
// 1. Interactive Result List: Click any result to highlight the asset in Project window.
|
||||
// 2. Wide Scope: Scans all text-based assets (Mat, PhysMat, Controller, Asset, etc.).
|
||||
// 3. Optimized Search: Faster file reading and progress bar with Cancel support.
|
||||
// 4. Clean UI: Integrated as a professional Editor Window.
|
||||
//
|
||||
// How to Use:
|
||||
// 1. Right-click any asset in the Project window.
|
||||
// 2. Select "Find References (Deep Scan)".
|
||||
// 3. View the results in the pop-up window.
|
||||
// ===============================================================================
|
||||
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace Editor
|
||||
{
|
||||
public class ReferenceFinderTool : EditorWindow
|
||||
{
|
||||
private static List<string> foundPaths = new List<string>();
|
||||
private static string targetAssetName = "";
|
||||
private static string targetAssetGUID = "";
|
||||
private Vector2 scrollPosition;
|
||||
|
||||
[MenuItem("Assets/Find References (Deep Scan)", false, 25)]
|
||||
public static void FindReferences()
|
||||
{
|
||||
Object selected = Selection.activeObject;
|
||||
if (selected == null) return;
|
||||
|
||||
string path = AssetDatabase.GetAssetPath(selected);
|
||||
targetAssetGUID = AssetDatabase.AssetPathToGUID(path);
|
||||
targetAssetName = selected.name;
|
||||
|
||||
if (string.IsNullOrEmpty(targetAssetGUID)) return;
|
||||
|
||||
PerformDeepScan();
|
||||
|
||||
// Open the results window
|
||||
ReferenceFinderTool window = GetWindow<ReferenceFinderTool>("Reference Finder");
|
||||
window.minSize = new Vector2(400, 300);
|
||||
window.Show();
|
||||
}
|
||||
|
||||
private static void PerformDeepScan()
|
||||
{
|
||||
foundPaths.Clear();
|
||||
|
||||
// We look for all assets that are usually saved in Text/YAML format
|
||||
// Added: Materials, Animators, ScriptableObjects, etc.
|
||||
string[] allGuids = AssetDatabase.FindAssets("t:Prefab t:Scene t:Material t:PhysicMaterial t:RuntimeAnimatorController t:ScriptableObject t:AnimatorOverrideController");
|
||||
|
||||
int total = allGuids.Length;
|
||||
|
||||
for (int i = 0; i < total; i++)
|
||||
{
|
||||
string assetPath = AssetDatabase.GUIDToAssetPath(allGuids[i]);
|
||||
|
||||
// Update Progress Bar
|
||||
bool isCanceled = EditorUtility.DisplayCancelableProgressBar(
|
||||
"Searching References",
|
||||
$"Scanning: {Path.GetFileName(assetPath)}",
|
||||
(float)i / total);
|
||||
|
||||
if (isCanceled) break;
|
||||
|
||||
// Check if the asset file contains the Target GUID
|
||||
if (FileContainsGUID(assetPath, targetAssetGUID))
|
||||
{
|
||||
foundPaths.Add(assetPath);
|
||||
}
|
||||
}
|
||||
|
||||
EditorUtility.ClearProgressBar();
|
||||
}
|
||||
|
||||
private static bool FileContainsGUID(string path, string guid)
|
||||
{
|
||||
if (!File.Exists(path)) return false;
|
||||
|
||||
// Using StreamReader is faster than File.ReadAllText for very large files
|
||||
using (StreamReader reader = new StreamReader(path))
|
||||
{
|
||||
string line;
|
||||
while ((line = reader.ReadLine()) != null)
|
||||
{
|
||||
if (line.Contains(guid)) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void OnGUI()
|
||||
{
|
||||
GUILayout.Label($"References for: {targetAssetName}", EditorStyles.boldLabel);
|
||||
EditorGUILayout.LabelField($"GUID: {targetAssetGUID}", EditorStyles.miniLabel);
|
||||
EditorGUILayout.Space();
|
||||
|
||||
if (foundPaths.Count == 0)
|
||||
{
|
||||
EditorGUILayout.HelpBox("No references found. Note: Ensure 'Asset Serialization' is set to 'Force Text' in Project Settings.", MessageType.Info);
|
||||
}
|
||||
else
|
||||
{
|
||||
GUILayout.Label($"Found {foundPaths.Count} items:", EditorStyles.label);
|
||||
|
||||
scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
|
||||
|
||||
for (int i = 0; i < foundPaths.Count; i++)
|
||||
{
|
||||
DrawResultItem(foundPaths[i]);
|
||||
}
|
||||
|
||||
EditorGUILayout.EndScrollView();
|
||||
}
|
||||
|
||||
EditorGUILayout.Space();
|
||||
if (GUILayout.Button("Rescan", GUILayout.Height(30)))
|
||||
{
|
||||
PerformDeepScan();
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawResultItem(string path)
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal("box");
|
||||
|
||||
// Get the asset icon
|
||||
Texture icon = AssetDatabase.GetCachedIcon(path);
|
||||
GUILayout.Label(icon, GUILayout.Width(16), GUILayout.Height(16));
|
||||
|
||||
// Display path
|
||||
GUILayout.Label(path, EditorStyles.wordWrappedLabel);
|
||||
|
||||
GUILayout.FlexibleSpace();
|
||||
|
||||
// Ping Button
|
||||
if (GUILayout.Button("Ping", GUILayout.Width(50)))
|
||||
{
|
||||
Object obj = AssetDatabase.LoadAssetAtPath<Object>(path);
|
||||
EditorGUIUtility.PingObject(obj);
|
||||
Selection.activeObject = obj;
|
||||
}
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user