有没有办法在EditorWindow脚本中使用serializedObject?

时间:2019-05-14 04:01:09

标签: c# unity3d

我有一个带有列表的脚本:

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEngine;

public class Test : MonoBehaviour
{
    public List<Conversation> conversations = new List<Conversation>();

当仅使用编辑器脚本而不使用EditorWindow时,我可以这样做:

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

[CustomEditor(typeof(Test))]
public class TestTriggerEditor : Editor
{
    private SerializedProperty _conversations;

    private void OnEnable()
    {
        _conversations = serializedObject.FindProperty("conversations");
    }

但是现在我想在EditorWindow脚本中完成它:

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

public class TestingEditorWindow : EditorWindow
{
    private SerializedProperty _conversations;

    [MenuItem("Testing/Editor")]
    private static void ConversationsSystem()
    {
        const int width = 340;
        const int height = 420;

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

        GetWindow<TestingEditorWindow>().position = new Rect(x, y, width, height);
    }

    private void OnGUI()
    {
        _conversations = serializedObject.FindProperty("conversations");
    }
}

但是我在OnGUI内部的行上遇到了错误:

_conversations = serializedObject.FindProperty("conversations");

错误出现在serializedObject上:

名称“ serializedObject”在当前上下文中不存在

如果我将其更改为SerializedObject,则会收到错误消息:

非静态字段,方法或属性'SerializedObject.FindProperty(string)'需要对象引用

我试图将_conversations更改为静态,但这无济于事。

我也想做:

SerializedObject serializedObject = new SerializedObject(

但不确定如何使用它。为什么在Editor脚本中可以正常工作,但在EditorWindow中却不能呢?

1 个答案:

答案 0 :(得分:0)

不同之处在于Editor

  1. 您可以看到

    显然与其中一种特定类型有关
    [CustomEditor(typeof(Test))]
    
  2. 更重要的是,它是附加到当前所选GameObject的一个特定实例的检查器。因此,您可以访问该serializedObject(或MonoBehaviour)的ScriptableObject实例

    请参阅Editor.serializedObject

      

    SerializedObject代表要检查的一个或多个对象。


EditorWindow的另一面与特定实例或GameObject 无关不相关,而只是将要打开的窗口。您可以说它生活在一种static环境中(而不是像Editor这样的实例化环境)。

因此,根本就没有serializedObject它与=>有关。它没有这样的属性。


使用SerializedObject当然是行不通的,因为这不是一个实例类型,并且方法FindProperty不是静态的,但由于错误消息试图告诉您,因此需要一个实例。

我不想听起来很糟糕,但是如果那是您还不了解的事情,那么您应该立即停止担心EditorScripting,并从基本的C#编码和/或一般面向对象的编程中获得一些刷新。 / p>


可以使用constructor

var serializedObject = new SerializedObject(referenceToTest);

如果,您将以某种方式获得对Test某个实例的引用。

您可以使用FindObjectOfType

var referenceToTest = FindObjectOfType<Test>();
if(! referenceToTest) return;

要从当前场景中获取第一个活动并启用的Test实例。

例如使用Selection.transforms

var selected = Selection.transforms;
Test referenceToTest;
foreach (var item in selected)
{
    referenceToTest = item.GetComponent<Test>();
    if(referenceToTest) break;
}

if(! referenceToTest) return;

从场景层次结构窗口中的选定对象中第一次遇到Test


或者,您可以从EditorWindow的检查器中打开该Test,而不是从static菜单栏中将其打开并传递MonoBehaviour引用。 (仅当Inspector保持打开状态时,直接传递serializedObject才有效,因为当不再选择GameObject时,serializedObject实例可能与TestEditor一起被销毁了)

[CustomEditor(typeof(Test))]
public class TestEditor : Editor
{
    public override void OnInpectorGUI ()
    {
        // Draw the default inspector
        DrawDefaultInspector();

        EditorGUILayout.Space();

        // Add a button for opening the EditorWindow and pass in the reference
        if(GUILayout.Button("Open EditorWindow"))
        {
            TestEditorWindow.ConversationsSystem((Test) target);
        }
    }
}

并接收参考并将其存储在

public class TestingEditorWindow : EditorWindow
{
    const int width = 340;
    const int height = 420;

    private SerializedProperty _conversations;

    private Test currentTestInstance;

    public static void ConversationsSystem(Test testInstance)
    { 
        var x = (Screen.currentResolution.width - width) / 2;
        var y = (Screen.currentResolution.height - height) / 2;

        var window = GetWindow<TestingEditorWindow>();

        window.position = new Rect(x, y, width, height);

        window.currentTestInstance = testInstance;
    }

    private void OnGUI()
    {
        if(! currentTestInstance)
        {
            EditorGUILayout.HelpBox("No Test instance selected!", MessageType.Error);
            return;
        }

        var serializedObject = new SerializedObject(currentTestInstance);

        _conversations = serializedObject.FindProperty("conversations");
    }
}

注意:在智能手机上键入内容,因此没有保修,但我希望这个主意会清楚