【Unity】「FindReferencesInProject2」を元に少し改造しました。
アセットの依存関係検索機能「FindReferencesInProject2」は高速に結果を表示しとても素晴らしいのですが、コンソールで結果が出るのみなので、もう少し使い勝手を良くしたいなと思いました。
目次
事前準備
FindReferencesInProject2 が動作する環境をまず準備してください。
ソースコード
元の FindReferencesInProject2 のソースコードを以下へ置き換えてください。その際にパスの修正も2点ほど書き換えてください。
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using UnityEditor;
using UnityEngine;
namespace FindReferencesInProjectEx
{
/// <summary>
/// アセットが参照しているアセットをリストアップする。
/// </summary>
public class FindReferencesInProjectEx : EditorWindow
{
private const string MenuItemName = "Assets/Find References In Project %#&f";
private const string MetaExtension = ".meta";
private static UnityEngine.Object selectedObject = default;
private static List<UnityEngine.Object> result = new List<UnityEngine.Object>();
private Vector2 scrollPosition = Vector2.zero;
[MenuItem(MenuItemName, false, 25)]
public static void Find()
{
bool isMacOS = Application.platform == RuntimePlatform.OSXEditor;
int totalWaitMilliseconds = isMacOS ? 2 * 1000 : 300 * 1000;
int cpuCount = Environment.ProcessorCount;
string appDataPath = Application.dataPath;
selectedObject = Selection.activeObject;
string selectedAssetPath = AssetDatabase.GetAssetPath(selectedObject);
string selectedAssetGUID = AssetDatabase.AssetPathToGUID(selectedAssetPath);
string selectedAssetMetaPath = selectedAssetPath + MetaExtension;
result.Clear();
var references = new List<string>();
var output = new System.Text.StringBuilder();
var stopwatch = new Stopwatch();
stopwatch.Start();
var psi = new ProcessStartInfo();
psi.WindowStyle = ProcessWindowStyle.Minimized;
if (isMacOS)
{
psi.FileName = "/usr/bin/mdfind";
psi.Arguments = string.Format("-onlyin {0} {1}", appDataPath, selectedAssetGUID);
}
else
{
psi.FileName = Path.Combine(Environment.CurrentDirectory, @"Assets\Editor\FindReferencesInProjectEx\rg.exe");
psi.Arguments = string.Format("--case-sensitive --follow --files-with-matches --no-text --fixed-strings " +
"--ignore-file Assets/Editor/FindReferencesInProjectEx/ignore.txt " +
"--threads {0} --regexp {1} -- {2}",
cpuCount, selectedAssetGUID, appDataPath);
}
psi.UseShellExecute = false;
psi.RedirectStandardOutput = true;
psi.RedirectStandardError = true;
var process = new Process();
process.StartInfo = psi;
process.OutputDataReceived += (sender, e) =>
{
if (string.IsNullOrEmpty(e.Data))
return;
string relativePath = e.Data.Replace(appDataPath, "Assets").Replace("\\", "/");
// skip the meta file of whatever we have selected
if (relativePath == selectedAssetMetaPath)
return;
references.Add(relativePath);
};
process.ErrorDataReceived += (sender, e) =>
{
if (string.IsNullOrEmpty(e.Data))
return;
output.AppendLine("Error: " + e.Data);
};
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
while (!process.HasExited)
{
if (stopwatch.ElapsedMilliseconds < totalWaitMilliseconds)
{
float progress = (float)((double)stopwatch.ElapsedMilliseconds / totalWaitMilliseconds);
string info = string.Format("Finding {0}/{1}s {2:P2}", stopwatch.ElapsedMilliseconds / 1000,
totalWaitMilliseconds / 1000, progress);
bool canceled = EditorUtility.DisplayCancelableProgressBar("Find References in Project", info, progress);
if (canceled)
{
process.Kill();
break;
}
Thread.Sleep(100);
}
else
{
process.Kill();
break;
}
}
foreach (string file in references)
{
string guid = AssetDatabase.AssetPathToGUID(file);
output.AppendLine(string.Format("{0} {1}", guid, file));
string assetPath = file;
if (file.EndsWith(MetaExtension))
{
assetPath = file.Substring(0, file.Length - MetaExtension.Length);
}
var asset = AssetDatabase.LoadMainAssetAtPath(assetPath);
result.Add(asset);
UnityEngine.Debug.Log(string.Format("{0}\n{1}", file, guid), asset);
}
EditorUtility.ClearProgressBar();
stopwatch.Stop();
GetWindow<FindReferencesInProjectEx>();
}
[MenuItem(MenuItemName, true)]
private static bool FindValidate()
{
var obj = Selection.activeObject;
if (obj != null && AssetDatabase.Contains(obj))
{
string path = AssetDatabase.GetAssetPath(obj);
return !AssetDatabase.IsValidFolder(path);
}
return false;
}
/// <summary>
/// 描画
/// </summary>
void OnGUI()
{
this.scrollPosition = GUILayout.BeginScrollView(this.scrollPosition);
GUILayout.Label($"{selectedObject.name}の検索結果");
if (result.Count > 0)
{
foreach (var referent in result)
{
var iconSize = EditorGUIUtility.GetIconSize();
EditorGUIUtility.SetIconSize(Vector2.one * 16);
if (GUILayout.Button(referent.name))
{
Selection.objects = new[] { referent };
}
EditorGUIUtility.SetIconSize(iconSize);
}
}
else
{
GUILayout.Label($"{selectedObject.name}はどこからも参照されていません。");
}
GUILayout.EndScrollView();
}
}
}