当前位置: 首页 > 知识库问答 >
问题:

为什么我在EditorWindow脚本中看不到OnGUI中的TextField?

丘畅
2023-03-14
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,在层次结构中选择游戏对象时,在编辑器窗口中显示它需要将近5秒的时间。

在此之前,一切都很快,并在编辑器窗口中显示整个层次结构。

现在它是空的:

我从这个问题中得到了答案:

可通过计算机搜索的

共有1个答案

沃楷
2023-03-14

<code>OnGUI</code>仅在鼠标(移动/单击)相应窗口时调用-

为了解决这个问题,您可以实现EditorWindow.OnSelectionChange并强制执行EditorWindow.Repaint,以便每次选择更改时刷新窗口。

private void OnSelectionChange()
{
    Repaint();
}

第二期制作如下:

GUILayout.TextField连同GUILayout.FlexibleSpace如果没有定义不同的使用自动插入文本的宽度-

相反,使用<code>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”相应的游戏对象!

自评论中询问以来的更新

如果你想包含递归选择的所有子元素,你可以这样做(可能有更好的方法,但这是我在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);

另一个更新

由于这可能不是很有效,您可能应该将它移到< code >搜索中,然后在< code>OnSelectionChange中仅刷新< code >选择的值,就像

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();
    }
}
 类似资料:
  • 我有一个简单的脚本,每2秒打印一次hello。 我有一个超简单的docker文件运行这个脚本。 首先我建立docker映像: 现在,我使用选项运行它,它按预期工作。 但是当我以分离模式运行它,然后尝试查看日志时,我什么也看不到。

  • Java程序。使用最新版本的eclipse和java。程序正常工作,但是我不明白为什么我看不到钟摆底部的圆。程序应该把钟摆显示为一条连接顶部和底部圆圈的线。我已经尝试了setFill()和setStroke()代码,但仍然无法解决这个问题...可能是一些小而简单的东西,但我错过了。请让我知道什么在我面前!

  • 我需要导航到我以前的活动。我想使用操作栏(工具栏)的向上箭头。我无法在我的操作栏(工具栏)中看到向上箭头。我在下面附上活动代码。 ImageActivity。Java语言 有没有人曾经面对过这种情况,并以某种方式找到了解决它的方法?提前谢谢。

  • 问题内容: 我希望服务器每分钟执行一次节点脚本。如果我手动执行文件(),该程序将完美执行,因此,我很确定这不是问题。但是,当我将其交给cron执行时,什么也没发生。 这是cron文件中的行。 这是一个示例日志: 可执行文件: 知道我为什么要广播静音吗?我应该在其他地方调试? 更新: 我相信问题与我的相对文件路径有关,并且main.js从其自己的目录外部执行。 所以现在,我已经放置在目录中。看起来像

  • 本页和本答案都引用了IP地址172.22.0.3。通过RFC 1918,它在专用网络范围172.16.0.0-172.31.255.255内。它也在我自己的代码中(在docker中运行),但我忘记了为什么。 是Docker默认吗?你能找到推荐人吗?

  • 问题内容: 我正在尝试编写一个小脚本以将当前目录更改为我的项目目录: 我将此文件另存为proj,使用添加了执行权限,然后将其复制到。当我通过以下方式调用它时 ,它什么也没做。我究竟做错了什么? 问题答案: Shell脚本在一个子Shell中运行,每个子Shell对当前目录都有自己的概念。的成功,但只要子shell退出,你是在交互式背壳和从来都没有改变,因此。 解决此问题的一种方法是改用别名: