C# 如何在编辑器窗口中以相同的大小显示Inspector窗口?

C# 如何在编辑器窗口中以相同的大小显示Inspector窗口?,c#,unity3d,C#,Unity3d,问题是,在Inspector中,它看起来很好,正如我所希望的,但在编辑器窗口中,控件和字段不在相同的位置 在屏幕截图中,检查器窗口位于右侧,编辑器窗口位于左侧。问题在于Inspector上的对话名称“名称”字段正好位于对话名称之后,但在编辑器窗口中,“名称”字段似乎略高于对话名称: 这是编辑器脚本: using System.Collections; using System.Collections.Generic; using UnityEditor; using UnityEditorIn

问题是,在Inspector中,它看起来很好,正如我所希望的,但在编辑器窗口中,控件和字段不在相同的位置

在屏幕截图中,检查器窗口位于右侧,编辑器窗口位于左侧。问题在于Inspector上的对话名称“名称”字段正好位于对话名称之后,但在编辑器窗口中,“名称”字段似乎略高于对话名称:

这是编辑器脚本:

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

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

    [SerializeField] private ReorderableList conversationsList;

    private SerializedProperty _conversations;

    private int _currentlySelectedConversationIndex = -1;
    private int newSize = 0;
    private Vector2 scrollPos;
    private SerializedProperty conversationsCounter;

    private readonly Dictionary<string, ReorderableList> _dialoguesListDict = new Dictionary<string, ReorderableList>();
    private readonly Dictionary<string, ReorderableList> _sentencesListDict = new Dictionary<string, ReorderableList>();

    private void OnEnable()
    {
        _conversationTrigger = (ConversationTrigger)target;
        _conversations = serializedObject.FindProperty("conversations");

        conversationsList = new ReorderableList(serializedObject, _conversations)
        {
            displayAdd = true,
            displayRemove = true,
            draggable = true,

            drawHeaderCallback = DrawConversationsHeader,

            drawElementCallback = DrawConversationsElement,

            onAddCallback = (list) =>
            {
                SerializedProperty addedElement;
                // if something is selected add after that element otherwise on the end
                if (_currentlySelectedConversationIndex >= 0)
                {
                    list.serializedProperty.InsertArrayElementAtIndex(_currentlySelectedConversationIndex + 1);
                    addedElement = list.serializedProperty.GetArrayElementAtIndex(_currentlySelectedConversationIndex + 1);
                }
                else
                {
                    list.serializedProperty.arraySize++;
                    addedElement = list.serializedProperty.GetArrayElementAtIndex(list.serializedProperty.arraySize - 1);
                }

                var name = addedElement.FindPropertyRelative("Name");
                var foldout = addedElement.FindPropertyRelative("Foldout");
                var dialogues = addedElement.FindPropertyRelative("Dialogues");

                name.stringValue = "";
                foldout.boolValue = false;
                dialogues.arraySize = 0;

                conversationsCounter = addedElement.FindPropertyRelative("ConversationIndex");
            },

            elementHeightCallback = (index) =>
            {
                return GetConversationHeight(_conversations.GetArrayElementAtIndex(index));
            }
        };
    }

    public override void OnInspectorGUI()
    {
        serializedObject.Update();

        // if there are no elements reset _currentlySelectedConversationIndex
        if (conversationsList.serializedProperty.arraySize - 1 < _currentlySelectedConversationIndex) _currentlySelectedConversationIndex = -1;

        EditorGUILayout.LabelField("Conversations", EditorStyles.boldLabel);
        EditorGUI.BeginChangeCheck();
        {
            newSize = EditorGUILayout.IntField(_conversations.arraySize);
        }
        if (EditorGUI.EndChangeCheck())
        {
            if (newSize > _conversations.arraySize)
            {
                // elements have to be added -> how many?
                var toAdd = newSize - _conversations.arraySize - 1;
                // why -1 ? -> We add the first element and set its values to default
                // now if we simply increase the arraySize for the rest of the elements
                // they will be all a copy of the first -> all defaults ;)

                // first add one element
                _conversations.arraySize++;
                // then get that element
                var newIndex = _conversations.arraySize - 1;
                var newElement = _conversations.GetArrayElementAtIndex(newIndex);

                // now reset all properties like
                var name = newElement.FindPropertyRelative("Name");
                name.stringValue = "";

                // now for the rest simply increase arraySize
                _conversations.arraySize += toAdd;
            }
            else
            {
                // for removing just make sure the arraySize is not under 0
                _conversations.arraySize = Mathf.Max(newSize, 0);
            }
        }

        scrollPos = EditorGUILayout.BeginScrollView(scrollPos, GUILayout.Height(250));

        GUILayout.Space(10);
        conversationsList.DoLayoutList();

        EditorGUILayout.EndScrollView();

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

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

        serializedObject.ApplyModifiedProperties();
    }

    #region Drawers

    #region List Headers

    private void DrawConversationsHeader(Rect rect)
    {
        //EditorGUI.LabelField(rect, "Conversations");
    }

    private void DrawDialoguesHeader(Rect rect)
    {
        EditorGUI.LabelField(rect, "Dialogues");
    }

    private void DrawSentencesHeader(Rect rect)
    {
        EditorGUI.LabelField(rect, "Sentences");
    }

    #endregion List Headers

    #region Elements

    private void DrawConversationsElement(Rect rect, int index, bool isActive, bool isFocused)
    {
        if (isActive) _currentlySelectedConversationIndex = index;

        var conversation = _conversations.GetArrayElementAtIndex(index);

        var position = new Rect(rect);

        var name = conversation.FindPropertyRelative("Name");
        var foldout = conversation.FindPropertyRelative("Foldout");
        var dialogues = conversation.FindPropertyRelative("Dialogues");
        string dialoguesListKey = conversation.propertyPath;

        EditorGUI.indentLevel++;
        {
            // make the label be a foldout
            //GUI.TextField(new Rect(position.x, position.y, 15, EditorGUIUtility.singleLineHeight), itemscounter.ToString());
            foldout.boolValue = EditorGUI.Foldout(new Rect(position.x, position.y, 10, EditorGUIUtility.singleLineHeight), foldout.boolValue, "Conversation Name ", true);
            name.stringValue = EditorGUI.TextField(new Rect(position.x + 120, position.y, 244, EditorGUIUtility.singleLineHeight), name.stringValue);

            if (foldout.boolValue)
            {
                // draw the name field
                //name.stringValue = EditorGUI.TextField(new Rect(position.x, position.y, position.width, EditorGUIUtility.singleLineHeight), name.stringValue);
                position.y += EditorGUIUtility.singleLineHeight;

                if (!_dialoguesListDict.ContainsKey(dialoguesListKey))
                {
                    // create reorderabl list and store it in dict
                    var dialoguesList = new ReorderableList(conversation.serializedObject, dialogues)
                    {
                        displayAdd = true,
                        displayRemove = true,
                        draggable = true,

                        drawHeaderCallback = DrawDialoguesHeader,

                        drawElementCallback = (convRect, convIndex, convActive, convFocused) => { DrawDialoguesElement(_dialoguesListDict[dialoguesListKey], convRect, convIndex, convActive, convFocused); },

                        elementHeightCallback = (dialogIndex) =>
                        {
                            return GetDialogueHeight(_dialoguesListDict[dialoguesListKey].serializedProperty.GetArrayElementAtIndex(dialogIndex));
                        },

                        onAddCallback = (list) =>
                        {
                            list.serializedProperty.arraySize++;
                            var addedElement = list.serializedProperty.GetArrayElementAtIndex(list.serializedProperty.arraySize - 1);

                            var newDialoguesName = addedElement.FindPropertyRelative("Name");
                            var newDialoguesFoldout = addedElement.FindPropertyRelative("Foldout");
                            var sentences = addedElement.FindPropertyRelative("Sentences");

                            newDialoguesName.stringValue = "";
                            newDialoguesFoldout.boolValue = true;
                            sentences.arraySize = 0;
                        }
                    };
                    _dialoguesListDict[dialoguesListKey] = dialoguesList;
                }

                _dialoguesListDict[dialoguesListKey].DoList(new Rect(position.x, position.y, position.width, position.height - EditorGUIUtility.singleLineHeight));
            }

        }
        EditorGUI.indentLevel--;
    }

    private void DrawDialoguesElement(ReorderableList list, Rect rect, int index, bool isActive, bool isFocused)
    {
        if (list == null) return;

        var dialog = list.serializedProperty.GetArrayElementAtIndex(index);

        var position = new Rect(rect);

        var foldout = dialog.FindPropertyRelative("Foldout");
        var name = dialog.FindPropertyRelative("Name");

        {
            // make the label be a foldout
            foldout.boolValue = EditorGUI.Foldout(new Rect(position.x, position.y, 10, EditorGUIUtility.singleLineHeight), foldout.boolValue, foldout.boolValue ? "" : name.stringValue);

            var sentencesListKey = dialog.propertyPath;
            var sentences = dialog.FindPropertyRelative("Sentences");

            if (foldout.boolValue)
            {
                // draw the name field
                name.stringValue = EditorGUI.TextField(new Rect(position.x, position.y, position.width, EditorGUIUtility.singleLineHeight), name.stringValue);
                position.y += EditorGUIUtility.singleLineHeight;

                if (!_sentencesListDict.ContainsKey(sentencesListKey))
                {
                    // create reorderabl list and store it in dict
                    var sentencesList = new ReorderableList(sentences.serializedObject, sentences)
                    {
                        displayAdd = true,
                        displayRemove = true,
                        draggable = true,

                        // header for the dialog list
                        drawHeaderCallback = DrawSentencesHeader,

                        // how a sentence is displayed
                        drawElementCallback = (sentenceRect, sentenceIndex, sentenceIsActive, sentenceIsFocused) =>
                        {
                            var sentence = sentences.GetArrayElementAtIndex(sentenceIndex);

                            // draw simple textArea for sentence
                            sentence.stringValue = EditorGUI.TextArea(sentenceRect, sentence.stringValue);
                        },

                        // Sentences have simply a fixed height of 2 lines
                        elementHeight = EditorGUIUtility.singleLineHeight * 2,

                        // when a sentence is added
                        onAddCallback = (sentList) =>
                        {
                            sentList.serializedProperty.arraySize++;
                            var addedElement = sentList.serializedProperty.GetArrayElementAtIndex(sentList.serializedProperty.arraySize - 1);

                            addedElement.stringValue = "";
                        }
                    };

                    // store the created ReorderableList
                    _sentencesListDict[sentencesListKey] = sentencesList;
                }

                // Draw the list
                _sentencesListDict[sentencesListKey].DoList(new Rect(position.x, position.y, position.width, position.height - EditorGUIUtility.singleLineHeight));
            }
        }
    }

    #endregion Elements

    #endregion Drawers


    #region Helpers

    #region HeightGetter

    /// <summary>
    /// Returns the height of given Conversation property
    /// </summary>
    /// <param name="conversation"></param>
    /// <returns>height of given Conversation property</returns>
    private float GetConversationHeight(SerializedProperty conversation)
    {
        var foldout = conversation.FindPropertyRelative("Foldout");

        // if not foldout the height is simply 1 line
        var height = EditorGUIUtility.singleLineHeight;

        // otherwise we sum up every controls and child heights
        if (foldout.boolValue)
        {
            // we need some more lines:
            //  for the Name field,
            // the list header,
            // the list buttons and a bit buffer
            height += EditorGUIUtility.singleLineHeight * 5;


            var dialogues = conversation.FindPropertyRelative("Dialogues");

            for (var d = 0; d < dialogues.arraySize; d++)
            {
                var dialog = dialogues.GetArrayElementAtIndex(d);
                height += GetDialogueHeight(dialog);
            }
        }

        return height;
    }

    /// <summary>
    /// Returns the height of given Dialogue property
    /// </summary>
    /// <param name="dialog"></param>
    /// <returns>height of given Dialogue property</returns>
    private float GetDialogueHeight(SerializedProperty dialog)
    {
        var foldout = dialog.FindPropertyRelative("Foldout");

        // same game for the dialog if not foldout it is only a single line
        var height = EditorGUIUtility.singleLineHeight;

        // otherwise sum up controls and child heights
        if (foldout.boolValue)
        {
            // we need some more lines:
            //  for the Name field,
            // the list header,
            // the list buttons and a bit buffer
            height += EditorGUIUtility.singleLineHeight * 4;

            var sentences = dialog.FindPropertyRelative("Sentences");

            // the sentences are easier since they always have the same height
            // in this example 2 lines so simply do
            // at least have space for 1 sentences even if there is none
            height += EditorGUIUtility.singleLineHeight * Mathf.Max(1, sentences.arraySize) * 2;
        }

        return height;
    }

    #endregion

    #endregion Helpers
}
这是编辑器窗口脚本:

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

public class ConversationsEditorWindow : EditorWindow
{
    private ConversationTriggerEditor editor;

    [MenuItem("Conversations/Conversations System")]
    static void Init()
    {
        const int width = 800;
        const int height = 800;

        var x = (Screen.currentResolution.width - width) / 2;
        var y = (Screen.currentResolution.height - height) / 2;

        var window = GetWindow<ConversationsEditorWindow>();
        var ff = FindObjectOfType<ConversationTrigger>();
        window.position = new Rect(x, y, width, height);
        window.editor = (ConversationTriggerEditor)Editor.CreateEditor(ff);
    }

    void OnGUI()
    {
        editor.OnInspectorGUI();
    }
}
使用系统集合;
使用System.Collections.Generic;
使用UnityEditor;
使用UnityEditorInternal;
使用UnityEngine;
公共类会话编辑器窗口:编辑器窗口
{
私人对话触发器编辑器;
[MenuItem(“对话/对话系统”)]
静态void Init()
{
常数int宽度=800;
const int height=800;
var x=(Screen.currentResolution.width-width)/2;
变量y=(Screen.currentResolution.height-height)/2;
var window=GetWindow();
var ff=FindObjectOfType();
window.position=新矩形(x,y,宽度,高度);
window.editor=(ConversationTriggerEditor)editor.CreateEditor(ff);
}
void OnGUI()
{
OnInspectorGUI();
}
}

区别似乎在于,Inspector
位置中的
指的是显示相应字段/属性的
Rect
。在EditorWindow中,可以看到它从左上角开始,而在Inspector中,有一点偏移。然后,对于编辑器窗口中的
对话名称
标签,标签/折页和ReorderableList的grib图标之间也有一点偏移。。不知道如何解决这个问题,您可以尝试在
EditorGUI.indentLevel++中包装
editor.OnInspectorGUI()
EditorGUI.indentLevel--不同之处似乎在于检查器中的
位置
指的是显示相应字段/属性的
矩形。在EditorWindow中,可以看到它从左上角开始,而在Inspector中,有一点偏移。然后,对于编辑器窗口中的
对话名称
标签,标签/折页和ReorderableList的grib图标之间也有一点偏移。。不知道如何解决这个问题,您可以尝试在
EditorGUI.indentLevel++中包装
editor.OnInspectorGUI()
EditorGUI.indentLevel--
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;

public class ConversationsEditorWindow : EditorWindow
{
    private ConversationTriggerEditor editor;

    [MenuItem("Conversations/Conversations System")]
    static void Init()
    {
        const int width = 800;
        const int height = 800;

        var x = (Screen.currentResolution.width - width) / 2;
        var y = (Screen.currentResolution.height - height) / 2;

        var window = GetWindow<ConversationsEditorWindow>();
        var ff = FindObjectOfType<ConversationTrigger>();
        window.position = new Rect(x, y, width, height);
        window.editor = (ConversationTriggerEditor)Editor.CreateEditor(ff);
    }

    void OnGUI()
    {
        editor.OnInspectorGUI();
    }
}