これはなに?
以前作った、
kakovail.info
こちら、右クリックでサクッと探したいな、と思ったり、リロードの問題があったりしたので、リファクタがてら書き直していました。
使い方と変わったところ
前回に追加して、Projectビューからお好きなスクリプトを右クリック→メニューから選択でも調べられるようになりました。(Assets/KEditorExtensions/から)
Sceneロードでのバグも消しました。
非アクティブなSceneの対処はちょっと保留です。
コード
// Copyright (c) 2021 Hiroyuki Kako // This software is released under the MIT License, see LICENSE. #if UNITY_EDITOR using System; using System.Collections.Generic; using System.Linq; using UnityEditor; using UnityEditor.SceneManagement; using UnityEngine; using UnityEngine.SceneManagement; public class ReferenceFinder : EditorWindow { private static string _targetComponentName; private static List<GameObject> _foundAssets = new List<GameObject>(); private static IEnumerable<Type> _cashedComponents; private static Dictionary<string, List<Type>> _typeDict; private static bool _isFirstTime = true; static MonoScript[] _monoScripts; private Vector2 _currentScrollPosition; [InitializeOnLoadMethod] private static void InitializeEvent() { EditorSceneManager.sceneClosing += OnClosing; } private static void OnClosing(Scene scene, bool removingScene) { if (!HasOpenInstances<ReferenceFinder>()) return; GetWindow<ReferenceFinder>().Close(); } [MenuItem("KEditorExtensions/Reference/ReferenceFinder")] private static void Open() { _cashedComponents = GetAllTypes(); GetWindow<ReferenceFinder>("Components Reference Finder."); } [MenuItem("Assets/KEditorExtensions/Find references in active scene and all prefabs")] private static void FindWithRightClick() { var name = Selection.activeObject; _cashedComponents = GetAllTypes(); GetWindow<ReferenceFinder>("Components Reference Finder."); _targetComponentName = name.name; SearchObjects(); } private void OnGUI() { EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("Never change Scene before reset this window"); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("This window can search active scene objects and all prefabs"); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); _targetComponentName = EditorGUILayout.TextField("Target Component Name: ", _targetComponentName); EditorGUILayout.EndHorizontal(); if (_foundAssets.Count > 0) { _currentScrollPosition = EditorGUILayout.BeginScrollView(_currentScrollPosition); foreach (var asset in _foundAssets) { EditorGUILayout.ObjectField(asset.name, asset, typeof(GameObject), false); } EditorGUILayout.EndScrollView(); } if (GUILayout.Button("Search")) { SearchObjects(); } } private static void SearchObjects() { _foundAssets.Clear(); var guids = AssetDatabase.FindAssets("t:GameObject", null); foreach (var guid in guids) { string path = AssetDatabase.GUIDToAssetPath(guid); var loadAsset = AssetDatabase.LoadAssetAtPath<GameObject>(path); var typeCash = GetType(_targetComponentName) ?? null; if (typeCash == null) { Debug.Log("No Type Found."); return; } var tmp = loadAsset.GetComponentsInChildren(GetType(_targetComponentName) ?? null); foreach (var kari in tmp) { _foundAssets.Add(kari.gameObject); } } var allObj = GetObjectsInAllScene(); foreach (var obj in allObj) { var typeCash = GetType(_targetComponentName) ?? null; var tmp = obj.GetComponentsInChildren(GetType(_targetComponentName) ?? null); if (typeCash == null) { Debug.Log("No Type Found."); return; } foreach (var kari in tmp) { _foundAssets.Add(kari.gameObject); } } } /// <summary> /// All script files that exist in the project /// </summary> static MonoScript[] MonoScripts { get { return _monoScripts ?? (_monoScripts = Resources.FindObjectsOfTypeAll<MonoScript>().ToArray()); } } /// <summary> /// Getting the type from the class name /// </summary> private static Type GetType(string className) { if (_typeDict == null) { _typeDict = new Dictionary<string, List<Type>>(); foreach (var type in _cashedComponents) { if (!_typeDict.ContainsKey(type.Name)) { _typeDict.Add(type.Name, new List<Type>()); } _typeDict[type.Name].Add(type); } } // If the class exists, show it in the list if (_typeDict.ContainsKey(className)) { return _typeDict[className][0]; } else { // If the class doesn't exist, get it just in case, and run again. if (_isFirstTime) { Debug.Log("Not found. ReScanning..."); _cashedComponents = GetAllTypes(); _isFirstTime = false; GetType(className); } _isFirstTime = true; return null; } } /// <summary> /// Get all class /// </summary> private static IEnumerable<Type> GetAllTypes() { var types = AppDomain.CurrentDomain.GetAssemblies() .SelectMany(asm => asm.GetTypes()) .Where(type => type != null && !string.IsNullOrEmpty(type.Namespace)) .Where(type => type.Namespace.Contains("UnityEngine")); var localTypes = MonoScripts .Where(script => script != null) .Select(script => script.GetClass()) .Where(classType => classType != null) .Where(classType => classType.Module.Name == "Assembly-CSharp.dll"); return types.Concat(localTypes).Distinct(); } private static GameObject[] GetObjectsInAllScene(bool includeInactive = true) { var sceneNumber = SceneManager.sceneCount; IEnumerable<GameObject> resultObjects = (GameObject[]) Enumerable.Empty<GameObject>(); for (int i = 0; i < sceneNumber; i++) { var obj = SceneManager.GetSceneAt(i).GetRootGameObjects(); resultObjects = resultObjects.Concat(obj); } return resultObjects.ToArray(); } } #endif