Почему я больше не вижу TextField внутри OnGUI в скрипте EditorWindow? - PullRequest
0 голосов
/ 18 марта 2019
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, и при выборе GameObject в Иерархии требуется почти 5 секунд, чтобы отобразить его в окне редактора.

А до этого все было быстро и показывало всю иерархию в окне редактора.

Теперь пусто:

Searchable window

Я взял ответ на этот вопрос:

Searchable

1 Ответ

2 голосов
/ 18 марта 2019

OnGUI вызывается только тогда, когда мышь (перемещается / щелкает) над соответствующим окном -> она не берет almost 5 seconds, но пока вы снова не наведете указатель мыши на окно.

В порядкечтобы решить, что вы можете реализовать EditorWindow.OnSelectionChange и заставить EditorWindow.Repaint, чтобы ваше окно обновлялось при каждом изменении Selection.

private void OnSelectionChange()
{
    Repaint();
}

Вторая проблема создается следующим образом:

GUILayout.TextField вместе с GUILayout.FlexibleSpace, если не определено иначе, автоматически использует ширину вставленного текста -> Поскольку у вас пустой текст в начале, ширина равна почти 0 ... вы на самом деле можете видеть, что ваше TextField очень тонкое, и оно увеличивается по мере заполнения:

enter image description here

ИспользованиеЯщики из 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);
}

, вы можетенажмите на имя и «пингуйте» соответствующий 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();
    }
}

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...