简体   繁体   English

unity ScriptableObject 多态 Arrays 序列化

[英]Unity ScriptableObject Polymorphic Arrays Serialization

The main issue is, I'm trying to use a polymorphic list in a ScriptableObject but its contents are lost when restarting Unity;主要问题是,我正在尝试在 ScriptableObject 中使用多态列表,但在重新启动 Unity 时其内容会丢失; code below.下面的代码。


So I've got a base class:所以我有一个基础 class:

[Serializable]
public class BaseAction : ScriptableObject
{
    public virtual void OnGUI()
    {
    }

    public virtual void ExecuteAction()
    {
    }
}

And an inheriting class with a simple string attribute:还有一个继承 class 的简单字符串属性:

[Serializable]
public class DebugLogAction : BaseAction
{
    [SerializeField]
    private string debugText = default;

    public override void OnGUI()
    {
        debugText = EditorGUILayout.TextField(debugText);
    }

    public override void ExecuteAction()
    {
        Debug.Log(debugText);
    }
}

They all reunite in a ScriptableObject that contains a list of BaseActions:它们都在一个包含 BaseAction 列表的 ScriptableObject 中重新组合:

[Serializable]
[CreateAssetMenu(fileName = "NewActionContainer", menuName = "ScriptableObjects/Action Container")]
public class ActionContainer : ScriptableObject
{
    [SerializeField]
    private List<BaseAction> actions = default;

    public void OnEnable()
    {
        if (actions == null)
        {
            actions = new List<BaseAction>();
        }
    }

    public void OnInspectorGUI()
    {
        foreach (var action in actions)
        {
            action.OnGUI();
        }

        if (GUILayout.Button("Add Debug Log Action"))
        {
            actions.Add(CreateInstance<DebugLogAction>());
        }
    }
}

I've written up a custom editor for the ActionContainer ScriptableObject which works fine, displaying the button for adding multiple actions which adds editable input fields:我已经为 ActionContainer ScriptableObject 编写了一个自定义编辑器,它工作正常,显示用于添加多个操作的按钮,该按钮添加了可编辑的输入字段:

[CustomEditor(typeof(ActionContainer)), CanEditMultipleObjects]
public class CustomActionContainerInspector : Editor
{
    private ActionContainer actionContainer;

    public void OnEnable()
    {
        actionContainer = (ActionContainer)target;
    }

    public override void OnInspectorGUI()
    {
        actionContainer.OnInspectorGUI();
    }
}

However, on restart of Unity, the content of the ScriptableObject is gone (assembly rebuilding is fine, playing/stopping the game keeps the data as well).但是,在重新启动 Unity 时,ScriptableObject 的内容消失了(程序集重建很好,播放/停止游戏也会保留数据)。

I've tried adding a field to BaseAction to check if the values are just sheared off the inheriting class, but no;我尝试向 BaseAction 添加一个字段来检查这些值是否刚刚从继承的 class 中剪掉,但没有; the entire list of actions from the ActionContainer empties. ActionContainer 中的整个操作列表都清空了。

I believe there's an issue either with serializing or deserializing the elements from the list itself, since it's polymorphic, but I've got no idea how to debug or solve the issue;我相信序列化或反序列化列表本身的元素存在问题,因为它是多态的,但我不知道如何调试或解决问题; internet searches didn't get me to a solution either.互联网搜索也没有让我找到解决方案。

First of all in general you should not call your method OnGUI as this is also a built-in message in MonoBehaviour and might lead to confusion.首先,一般来说,您不应该调用您的方法OnGUI ,因为这也是MonoBehaviour中的内置消息,可能会导致混淆。

Your main pitfall I think is the dirty state.我认为你的主要缺陷是肮脏的 state。

If you don't mark objects dirty after changing them then your changes don't get saved correctly.如果您在更改对象后没有将它们标记为脏,那么您的更改将无法正确保存。

I think a quick fix for this would be to use EditorUtility.SetDirty我认为对此的快速解决方法是使用EditorUtility.SetDirty

public override void OnGUI()
{
    EditorGUI.BeginChangeCheck();
    debugText = EditorGUILayout.TextField(debugText);
    if(EditorGUI.EndChangeCheck())
    {
        EditorUtility.SetDirty(this);
    }
}

or if you wan to properly support undo/redo then rather usingUndo.RecordObject或者如果您想正确支持撤消/重做,那么宁可使用Undo.RecordObject

public override void OnGUI()
{
    EditorGUI.BeginChangeCheck();
    var newDebugText = EditorGUILayout.TextField(debugText);
    if(EditorGUI.EndChangeCheck())
    {
        Undo.RecordObject(this, "changed debug text");
        debugText = newDebugText;
    }
}

See also也可以看看

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM