Unity3D Editor:如何找到给定资产的所有用法?
Unity3D Editor: How can I find all usages of a given asset?
非常有用的功能"Find usages"存在于Visual Studio和Resharper中,但我在Unity3D Editor中找不到相同的功能。我在Unity3d中只看到"Select dependencies",但我需要相反的。存在吗?
从编辑器中,转到项目选项卡,select给定的资产,右键单击它,然后单击在其中查找引用场景。如果给定资产是脚本,它将在 层次视图 中向您显示给定资产附加到的每个游戏对象。如果它是图像、音频文件或预制件,它会在 Hierarchy View.
中显示哪个 GameObject 正在使用该资产
遗憾的是,Unity Editor 仅允许您在场景中查找资源的用法。
- 此外,您得到的是使用它的选定资产列表,因此在更改鼠标焦点后您将失去选择
Asset Store 上有一个解决方案可以:
- 在项目和场景视图中查找资产的所有用法
- 在单独的 window 中展示结果,显示使用目标资产的特定字段
- 允许您用拖放替换特定的资源使用
GIF 演示功能和界面:
资源商店link:
Unity Answers 中的这个脚本做得很好。 (也可以很容易地稍微调整以改进其功能)
来源: http://answers.unity.com/answers/1509032/view.html
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
免费的开源工具 Dependencies-Hunter 可以完成这项工作:查找给定资产的所有 dependencies/usages。它还可以执行完整的项目分析以找到所有未使用的资产。
它由一个脚本组成,因此只需将其复制粘贴到您的项目中即可。
它在内部使用 AssetDatabase.GetDependencies 构建所有资产的地图以用于分析。
所以它有两个选项可供使用:
- 它在资产上下文菜单中添加了一个选项“在项目中查找引用”,该菜单显示了该特定资产具有的依赖项。 The resulting window looks like this
- 还有一个选项可以通过单独的编辑器查找项目中所有未使用的资产 window。您可以通过指定要忽略的内容的 RegExp 模式来过滤资产以进行分析。
以上解决方案实际上是不正确的。 Unity 确实支持在项目视图中查找对资产的引用,但没有按钮。您必须在项目视图搜索栏中手动输入查询:带有文件扩展名的“ref:Assets//”。当您在场景中查找引用时,这与它放入场景视图搜索中的查询完全相同。 unity 需要一点时间来“思考”,但它最终会吐出对你的 asset/script.
的引用
非常有用的功能"Find usages"存在于Visual Studio和Resharper中,但我在Unity3D Editor中找不到相同的功能。我在Unity3d中只看到"Select dependencies",但我需要相反的。存在吗?
从编辑器中,转到项目选项卡,select给定的资产,右键单击它,然后单击在其中查找引用场景。如果给定资产是脚本,它将在 层次视图 中向您显示给定资产附加到的每个游戏对象。如果它是图像、音频文件或预制件,它会在 Hierarchy View.
中显示哪个 GameObject 正在使用该资产遗憾的是,Unity Editor 仅允许您在场景中查找资源的用法。
- 此外,您得到的是使用它的选定资产列表,因此在更改鼠标焦点后您将失去选择
Asset Store 上有一个解决方案可以:
- 在项目和场景视图中查找资产的所有用法
- 在单独的 window 中展示结果,显示使用目标资产的特定字段
- 允许您用拖放替换特定的资源使用
GIF 演示功能和界面:
资源商店link:
Unity Answers 中的这个脚本做得很好。 (也可以很容易地稍微调整以改进其功能)
来源: http://answers.unity.com/answers/1509032/view.html
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
免费的开源工具 Dependencies-Hunter 可以完成这项工作:查找给定资产的所有 dependencies/usages。它还可以执行完整的项目分析以找到所有未使用的资产。
它由一个脚本组成,因此只需将其复制粘贴到您的项目中即可。
它在内部使用 AssetDatabase.GetDependencies 构建所有资产的地图以用于分析。
所以它有两个选项可供使用:
- 它在资产上下文菜单中添加了一个选项“在项目中查找引用”,该菜单显示了该特定资产具有的依赖项。 The resulting window looks like this
- 还有一个选项可以通过单独的编辑器查找项目中所有未使用的资产 window。您可以通过指定要忽略的内容的 RegExp 模式来过滤资产以进行分析。
以上解决方案实际上是不正确的。 Unity 确实支持在项目视图中查找对资产的引用,但没有按钮。您必须在项目视图搜索栏中手动输入查询:带有文件扩展名的“ref:Assets//”。当您在场景中查找引用时,这与它放入场景视图搜索中的查询完全相同。 unity 需要一点时间来“思考”,但它最终会吐出对你的 asset/script.
的引用