首页 > 解决方案 > 如何避免 ScriptableObject 数据结构更改时的数据丢失

问题描述

我正在使用ScriptableObject资产来存储我的多语言应用程序项目的数据。这很好用,除了我想更改现有数据结构的情况。

就我而言,数据结构如下所示:

[CreateAssetMenu(fileName = "Data", menuName = "ScriptableObjects/I18NData", order = 1)]
public class I18NData : ScriptableObject
{
    public I18NSpriteData[] Sprites;
    public I18NTextData[] Texts;
}

[System.Serializable]
public class I18NSpriteData
{
    public string Label;
    public Sprite SpriteEN;
    public Sprite SpriteFR;
    public Sprite SpriteSG;
    public Sprite SpriteES;
    public Sprite SpriteDE;
    public Sprite SpriteIT;
}

[System.Serializable]
public class I18NTextData
{
    public string Label;

    [TextArea]
    public string TextEN;

    [TextArea]
    public string TextFR;

    [TextArea]
    public string TextSG;

    [TextArea]
    public string TextES;

    [TextArea]
    public string TextDE;

    [TextArea]
    public string TextIT;
}

现在我在 Unity 编辑器中添加数据,一切正常。但是,一旦我对现有数据结构进行了更改,编辑器中的所有数据都会丢失。ScriptableObject 似乎被重置为空状态。

这尤其令人讨厌,因为我们正处于开发过程中,并且在这个阶段数据结构的变化是不可避免的......

为了避免这种情况,你会怎么做?您是否有一些基于其他文件(例如 JSON)生成 ScriptableObjects 的脚本?还是在 Unity 中有一种简单的方法?

感谢您的任何提示!

标签: c#unity3d

解决方案


如果要重命名序列化字段,但保留数据,Unity 有一个名为FormerlySerializedAs的属性,它将保留旧的序列化字段名称。

[CreateAssetMenu(fileName = "Data", menuName = "ScriptableObjects/I18NData", order = 1)]
public class I18NData : ScriptableObject
{

    [FormerlySerializedAs("Sprites")]
    public I18NSpriteData[] Sprites2;
    public I18NTextData[] Texts;
}

另一种选择是您可以将字段设为私有并使用SerializeField属性。然后,您可以随时间自由更改访问或修改字段的属性,而不会影响序列化:

[CreateAssetMenu(fileName = "Data", menuName = "ScriptableObjects/I18NData", order = 1)]
public class I18NData : ScriptableObject
{
    [SerializeField]
    private I18NSpriteData[] Sprites;
    public I18NSpriteData[] Sprites2 {
            get { return Sprites; }
            set { Sprites = value; }
    }

    [SerializeField]
    private I18NTextData[] Texts;
    public I18NTextData[] Texts2 {
            get { return Texts; }
            set { Texts= value; }
    }
}

您可能要考虑的另一件事是使用ISerializationCallbackReceiver接口来更好地控制 Unity 的序列化过程。它提供了两个方法,OnBeforeSerialize 和 OnAfterDeserialize,在 Unity 的序列化和反序列化过程中调用。

This is probably more useful when serializing complex structures that Unity can't normally handle, like Dictionaries, but depending on the types of changes you are making it might be helpful. You could potentially use it for migrating data between revisions.


推荐阅读