我该如何在检视面板中设置GUI.Button的位置?

3
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;

[CustomEditor(typeof(ConversationTrigger))]
public class ConversationTriggerEditor : Editor
{
    private ConversationTrigger conversationtrigger;

    private void OnEnable()
    {
        conversationtrigger = FindObjectOfType<ConversationTrigger>();
    }

    public override void OnInspectorGUI()
    {
        DrawDefaultInspector();

        if(GUI.Button(new Rect(0.1f,0.5f,0.1f,0.1f), "Add new item"))
        {
            conversationtrigger.conversations.Add(new Conversation());
        }

        if (GUILayout.Button("Save Conversations"))
        {
            conversationtrigger.SaveConversations();
        }

        if (GUILayout.Button("Load Conversations"))
        {
            Undo.RecordObject(conversationtrigger, "Loaded conversations from JSON");
            conversationtrigger.LoadConversations();
        }
    }
}

我尝试了这行代码:

if(GUI.Button(new Rect(0.1f,0.5f,0.1f,0.1f), "Add new item"))

但这会让按钮消失,就像被删除一样。 如果我使用GUILayout.Button,我会看到按钮,但是我不能设置按钮位置,所以我使用GUI.Button

我想要将按钮"Add new item"定位在Canvas字段之前,并始终在最后一个对话项之后,即此案例中的Locked Room。如果我添加一个新项,按钮应该留在新添加的项之后并在Canvas字段之前保持不变。

我猜测Rect的这些值是错误的,使得按钮被定位在窗口之外。

这是检查器的屏幕截图:

Inspector

1个回答

3

Rect中的值为positionXpositionYwidthheight,而在检查器中,它们以像素为单位。因此

new Rect(0.1f,0.5f,0.1f,0.1f)

简单来说,这会导致当前检查器中一个非常小的按钮,大小仅为0.1 x 0.1像素,位于0.1,0.5像素的位置。由于屏幕上不能显示大小为0.1像素的内容,所以它是看不见的。
据我所知,您可以使用GUILayoutUtility.GetLastRect,以获取按钮之前的最后一个控件的Rect,然后使用该Rect放置您的按钮,例如:
Rect lastRect = GUILayoutUtility.GetLastRect();

Rect buttonRect = new Rect(lastRect.x, lastRect.y + EditorGUIUtility.singleLineHeight, 100, 30);

if(GUI.Button(buttonRect, "AddNewItem")
    ...

要将按钮放置在最后一个控件的下一行,并将其大小设置为100px * 30px


然而,总体上我建议不要混合使用GUIGUILayout。这有点类似于在css中混合使用staticrelative


取决于你想要改变的具体内容,你可能更想使用可选的options参数,例如改变按钮的高度和宽度。

GUILayout.Button("AddNewItem", GUILayout.With(100), GUILayout.Height(30));

如果您想要更改按钮在X轴上的起始位置,可以通过暂时更改EditorGUI.indentLevel来实现。

EditorGUI.indentLevel++
GUILayout.Button("AddNewItem", GUILayout.With(100), GUILayout.Height(30));
EditorGUI.indentLevel--;

要在 Y 方向上更改位置,您可以使用EditorGUILayout.Space

EditorGUILayout.Space();
if(GUILayout.Button(...))

为了在按钮和控件之间有一个小的默认空格,可以使用GUILayout.Space等方法。
GUILayout.Space(30);
if(GUILayout.Button(...))

要设置固定像素空间。


针对您的实际问题

如果您真的想在控件之间放置按钮,那么您无法绕过实现整个检查器的编辑器而不是使用DrawDefaultInspector,因为这也意味着您必须为按钮腾出空间。否则,您可能会在彼此之上获得多个控件。

我不会在这里为您做这件事。我们甚至看不到您类的字段/类型。

但由于您正在使用列表/数组,因此我(就像我经常做的那样)再次强烈建议使用未记录的ReorderableList,它不仅非常时尚,可以让您通过拖放重新排列列表中的项目,还默认实现了AddRemove按钮。


我也可以问一下您为什么要这么做?

conversationtrigger = FindObjectOfType<ConversationTrigger>();

只要你遇到非活跃的游戏物体、禁用的 ConversationTrigger、预制件或者场景中有多个这些组件,此操作就会失败。
在编辑器中,您已经可以通过target获取当前检查的组件。您所要做的就是进行转换。
conversationtrigger = (ConversationTrigger) target;

注意:本文使用智能手机输入,没有保修但希望能够清晰表达思想


我能够使用您提供的链接中的ReorderableList。现在我可以拖动项目并使用+和-添加/删除项目。但是,当单击+时,如何使其添加新的空列表项(Conversation)?当双击其中一个项目或制作箭头以折叠项目并显示所有子项(如我的问题中的Opening和其他子项)时,如何实现? - yochi le
1
我很乐意在新问题中帮助你解决这些问题 ;) - derHugo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接