[英]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.