using UnityEngine;
using UnityEditor;
public class SearchableWindow : EditorWindow
{
string searchString = "";
[MenuItem("Tools/Searching")]
private static void Searching()
{
const int width = 340;
const int height = 420;
var x = (Screen.currentResolution.width - width) / 2;
var y = (Screen.currentResolution.height - height) / 2;
GetWindow<SearchableWindow>().position = new Rect(x, y, width, height);
}
void OnGUI()
{
GUILayout.BeginHorizontal(EditorStyles.toolbar);
GUILayout.FlexibleSpace();
searchString = GUILayout.TextField(searchString, EditorStyles.toolbarTextField);
GUILayout.EndHorizontal();
var items = Selection.gameObjects;
// Do comparison here. For example
for (int i = 0; i < items.Length; i++)
{
if (items[i].name.Contains(searchString))
{
GUILayout.Label(items[i].name);
}
}
}
}
在运行正常之前,但是现在一切都很缓慢,而且我也看不到TextField,并且在Hierarchy中选择GameObject时,要花费近5秒钟才能在Editor窗口中显示它。
在此之前,一切很快,并在“编辑器”窗口中显示了整个层次结构。
现在它是空的:
我从以下问题中得到了答案:
答案 0 :(得分:2)
OnGUI
仅在鼠标(在移动/单击)相应窗口上时被调用->它不会占用almost 5 seconds
,而是直到再次将鼠标移到窗口上。
为了解决此问题,您可以实施EditorWindow.OnSelectionChange
并强制使用EditorWindow.Repaint
,以便每次Selection
更改时刷新窗口。
private void OnSelectionChange()
{
Repaint();
}
第二期如下:
GUILayout.TextField
和GUILayout.FlexibleSpace
(如果未定义)一起自动使用插入文本的宽度->由于开始时的文本为空,因此宽度几乎为 0。 ..实际上,您可以看到那里的TextField非常薄,并且随着它的填充它会变大:
使用EditorGUILayout
中的抽屉可以解决此问题:
EditorGUILayout.BeginHorizontal(EditorStyles.toolbar);
GUILayout.FlexibleSpace();
searchString = EditorGUILayout.TextField(searchString, EditorStyles.toolbarTextField);
EditorGUILayout.EndHorizontal();
var items = Selection.gameObjects;
// Do comparison here. For example
foreach (var selectedObject in selected)
{
if (selectedObject .name.Contains(searchString))
{
EditorGUILayout.LabelField(selectedObject.name);
}
}
提示(如果替换)
EditorGUILayout.LabelField(items[i].name);
使用
if (GUILayout.Button(selectedObject.name, EditorStyles.label))
{
EditorGUIUtility.PingObject(selectedObject);
}
您可以单击名称,然后在层级中“ ping”相应的GameObject!
更新,因为已在评论中询问
如果要包括选择递归的所有子项,可以执行类似的操作(可能会有更好的方法,但这就是我在10分钟之内得出的结论)
private static IEnumerable<GameObject> GetChildrenRecursive(GameObject root)
{
var output = new List<GameObject>();
//add the root object itself
output.Add(root);
// iterate over direct children
foreach (Transform child in root.transform)
{
// add the child itslef
output.Add(child.gameObject);
// Recursion here: Get all subchilds of this child
var childsOfchild = GetChildrenRecursive(child.gameObject);
output.AddRange(childsOfchild);
}
return output;
}
private static IEnumerable<GameObject> GetChildrenRecursive(IEnumerable<GameObject> rootObjects)
{
var output = new List<GameObject>();
foreach (var root in rootObjects)
{
output.AddRange(GetChildrenRecursive(root));
}
// remove duplicates
return output.Distinct().ToList();
}
并使用
var selected = GetChildrenRecursive(Selection.gameObjects);
另一个更新
由于这可能不是很有效,您可能应该将其移至Searching
,而不是像这样在selected
中刷新OnSelectionChange
值
public class SearchableWindow : EditorWindow
{
private string searchString = "";
private List<GameObject> selected;
[MenuItem("Tools/Searching")]
private static void Searching()
{
const int width = 340;
const int height = 420;
var x = (Screen.currentResolution.width - width) / 2;
var y = (Screen.currentResolution.height - height) / 2;
var window = GetWindow<SearchableWindow>();
window.position = new Rect(x, y, width, height);
window.selected = GetChildrenRecursive(Selection.gameObjects).ToList();
}
private void OnSelectionChange()
{
selected = GetChildrenRecursive(Selection.gameObjects).ToList();
Repaint();
}
private void OnGUI()
{
EditorGUILayout.BeginHorizontal(EditorStyles.toolbar);
GUILayout.FlexibleSpace();
searchString = EditorGUILayout.TextField(searchString, EditorStyles.toolbarTextField);
EditorGUILayout.EndHorizontal();
// only as fallback
if (selected == null)
{
selected = GetChildrenRecursive(Selection.gameObjects).ToList();
}
// Do comparison here. For example
foreach (var selectedObject in selected)
{
if (selectedObject.name.Contains(searchString))
{
if (GUILayout.Button(selectedObject.name, EditorStyles.label))
{
EditorGUIUtility.PingObject(selectedObject);
}
}
}
}
private static IEnumerable<GameObject> GetChildrenRecursive(GameObject root)
{
var output = new List<GameObject>();
//add the root object itself
output.Add(root);
// iterate over direct children
foreach (Transform child in root.transform)
{
// add the children themselves
output.Add(child.gameObject);
var childsOfchild = GetChildrenRecursive(child.gameObject);
output.AddRange(childsOfchild);
}
return output;
}
private static IEnumerable<GameObject> GetChildrenRecursive(IEnumerable<GameObject> rootObjects)
{
var output = new List<GameObject>();
foreach (var root in rootObjects)
{
output.AddRange(GetChildrenRecursive(root));
}
// remove any duplicates that would e.g. appear if you select a parent and its child
return output.Distinct();
}
}