Unity:将精灵保存/加载为Json

时间:2017-06-02 08:10:00

标签: c# json unity3d unity5

我正在学习一个教程,我需要保存属于对象的精灵。 我正在创建一个项目数据库,当然希望项目附带正确的图像。这就是我构建项目数据库的方式:

ItemObject

[System.Serializable]
public class ItemObject{

    public int id;
    public string title;
    public int value;
    public string toolTip;
    public bool stackable;
    public string category;
    public string slug;
    public Sprite sprite;


    public ItemObject(int id, string title, int value, string toolTip, bool stackable, string category, string slug)
    {
        this.id = id;
        this.title = title;
        this.value = value;
        this.toolTip = toolTip;
        this.stackable = stackable;
        this.category = category;
        this.slug = slug;
        sprite = Resources.Load<Sprite>("items/" + slug);
    }

的ItemData

[System.Serializable]
public class ItemData {

    public List<ItemObject> itemList;

}

然后我保存/加载ItemData.itemList。这很好用。正如你所看到的,我使用“slug”来加载我的Item的sprite,slug基本上是一个代码友好的名字(例如:golden_hat),然后我的Sprite名字也一样。

这也很好用,但是Unity保存了Sprite InstanceID,它在启动时总是会改变,所以如果我退出Unity并加载我的数据,它将得到错误的Image。

我的Json:

{
    "itemList": [
        {
            "id": 0,
            "title": "Golden Sword",
            "value": 111,
            "toolTip": "This is a golden sword",
            "stackable": false,
            "category": "weapon",
            "slug": "golden_sword",
            "sprite": {
                "instanceID": 13238
            }
        },
        {
            "id": 1,
            "title": "Steel Gloves",
            "value": 222,
            "toolTip": "This is steel gloves",
            "stackable": true,
            "category": "weapon",
            "slug": "steel_gloves",
            "sprite": {
                "instanceID": 13342
            }
        }
    ]
}

所以我猜它不会这样做,有没有其他方法来保存Json中的Sprite?或者每次使用我的“slug”时我是否必须在运行时加载正确的Sprite?

2 个答案:

答案 0 :(得分:1)

如果您正在使用JsonUtility进行序列化,则可以实施ISerializationCallbackReceiver以接收序列化回调。这样,您可以在反序列化对象后根据存储的路径加载正确的sprite。您还可以避免资源重复。

[Serializable]
public class ItemObject : ISerializationCallbackReceiver
{
    public void OnAfterDeserialize()
    {
        sprite = Resources.Load<Sprite>("items/" + slug);
        Debug.Log(String.Format("Loaded {0} from {1}", sprite, slug));
    }

    public void OnBeforeSerialize() { }

    (...)
}

如果确实想要将精灵直接存储在JSON中,请考虑序列化从Sprite.texture.GetRawTextureData()获取的原始纹理数据(可能将二进制数据存储在base64 string中)并使用Sprite.Create()在运行时重新创建它。 ISerializationCallbackReceiver技巧也适用于此。

另外请注意,如果它符合您的要求,请务必考虑删除基于JSON的对象数据库,转而使用Scriptable Objects。通过这种方式,您可以轻松引用UnityEngine对象,而无需使用Resources文件夹(除非必要,否则不建议这样做。)

答案 1 :(得分:0)

更合适的方法是将纹理保存为byte [],然后你的json包含byte []的名称或url。

    {
        "id": 1,
        "title": "Steel Gloves",
        "value": 222,
        "toolTip": "This is steel gloves",
        "stackable": true,
        "category": "weapon",
        "slug": "steel_gloves",
        "sprite": "steelgloves"
    }

然后当你抓住json时,转换为C#并查找字节数组。一旦你有了字节数组,就可以重建精灵:

byte [] bytes = File.ReadAllBytes(path);
Texture2d tex = new Texture2D(4,4);
tex.LoadImage(bytes);
Sprite sp = Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height), new Vector2(0.5f,0.5f));