如何将序列化对象从编辑器脚本传递到编辑器窗口脚本?

时间:2019-07-17 08:21:47

标签: c# unity3d

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

[CustomEditor(typeof(ConversationTrigger))]
public class ConversationTriggerEditor : Editor
{
    public ConversationsEditorWindow initser()
    {
        ConversationsEditorWindow myWindow = CreateInstance<ConversationsEditorWindow>();
        //myWindow.Init(serializedObject);
        SerializedObject serobject = new SerializedObject(myWindow);
        myWindow.Init(serobject);

        return myWindow;
    }

    public override void OnInspectorGUI()
    {
        if (GUILayout.Button("Configure Item"))
        {
            ConversationsEditorWindow myWindow = CreateInstance<ConversationsEditorWindow>();
            //myWindow.Init(serializedObject);
            myWindow.Init(serializedObject);
        }
    }
}

第一次使用OnInspectorGUI中的按钮,它在该按钮上工作正常。但是现在我不希望在“编辑器”脚本中使用按钮,而是在“编辑器窗口”脚本中使用项目菜单。

所以我在编辑器脚本中创建了一个称为initser的方法。

然后在编辑器窗口中:

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

public class ConversationsEditorWindow : EditorWindow
{
    public static SerializedObject conversation = null;

    private static ConversationTrigger _conversationTrigger;

    [SerializeField] private static ReorderableList conversationsList;

    private static SerializedProperty _conversations;

    private static int _currentlySelectedConversationIndex = -1;
    private static int newSize = 0;
    private static Vector2 scrollPos;

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

    private static SerializedObject itemcopy;

    [MenuItem("Dialog System/Conversations")]
    private static void ConversationsWindow()
    {
        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>();
        window.position = new Rect(x, y, width, height);

        ConversationTriggerEditor triggereditor = new ConversationTriggerEditor();
        triggereditor.initser();
    }


    public void Init(SerializedObject _item)
    {
        // Copy the Item targetObject to not lose reference when you
        // click another element on the project window.
        itemcopy = new SerializedObject(_item.targetObject);
        conversation = itemcopy;

        // Other things to initialize the window
        _conversationTrigger = (ConversationTrigger)_item.targetObject;
        _conversations = itemcopy.FindProperty("conversations");

        conversationsList = new ReorderableList(itemcopy, _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;
            },

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

    private void OnGUI()
    {
        if (itemcopy != null)
        {
            itemcopy.Update();

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

现在对话列表为空。

在此之前,当我在“编辑器”脚本中使用按钮时,我在这里使用菜单项而不是使其静态化:

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

public class ConversationsEditorWindow : EditorWindow
{
    public static SerializedObject conversation = null;

    private static ConversationTrigger _conversationTrigger;

    [SerializeField] private static ReorderableList conversationsList;

    private static SerializedProperty _conversations;

    private static int _currentlySelectedConversationIndex = -1;
    private static int newSize = 0;
    private static Vector2 scrollPos;

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

    private static SerializedObject itemcopy;




    public void Init(SerializedObject _item)
    {
        // Copy the Item targetObject to not lose reference when you
        // click another element on the project window.
        itemcopy = new SerializedObject(_item.targetObject);
        conversation = itemcopy;

        // Other things to initialize the window
        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>();
        window.position = new Rect(x, y, width, height);

        _conversationTrigger = (ConversationTrigger)_item.targetObject;
        _conversations = itemcopy.FindProperty("conversations");

        conversationsList = new ReorderableList(itemcopy, _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;
            },

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

最后,我要做的是将序列化对象从编辑器脚本传递到编辑器窗口脚本,而在编辑器脚本中没有按钮。

1 个答案:

答案 0 :(得分:1)

您不想像在SerializedObject中那样创建EditorWindow实例的serobject = new SerializedObject(myWindow);,而是传递编辑脚本的serializedObject引用。< / p>

主要问题:您不能简单地使用

ConversationTriggerEditor triggereditor = new ConversationTriggerEditor();

这没有任何意义。一旦相应的ConversationTriggerEditor实例获得焦点并加载了检查器,则ConversationTrigger实例将由Unity内部创建。如果您使用new创建实例,那么该ConversationTriggerEditor实例应该如何知道它属于哪个实际ConversationTrigger组件?


相反,您必须以某种方式获取相应的ConversationTrigger实例的引用,例如使用

var conversationTrigger = FindObjectOfType<ConversationTrigger>();

,然后使用

从中创建SerializedObject
var conversationTriggerSerializedObject = new SerializedObject(conversationTrigger);

请注意,将conversationTriggerSerializedObject的所有更改也都包含在其中

conversationTriggerSerializedObject.Update();

// ...

conversationTriggerSerializedObject.ApplyModifiedProperties();