Unity: saving / loading sprites as Json
I followed a tutorial in which I need to save a sprite that belongs to an object. I am creating a database of items and of course I want the correct image to appear along with the item. This is how I created my Item database:
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 STRONG>
[System.Serializable]
public class ItemData {
public List<ItemObject> itemList;
}
Then I save / Load ItemData.itemList. This works great. As you can see I am using "slug" to load my Item sprite, slug is basically a codename (ex: golden_hat) then I have the same name for my sprite.
This also works great, but Unity keeps the Sprite InstanceID that always changes on startup, so if I exit Unity and load my data, it gets the wrong image.
My 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
}
}
]
}
So my guess is it won't work to do it this way, is there any other way to save Sprite to Json? Or do I need to load the correct sprite at runtime every time using my "slug"?
source to share
A more suitable way would be to store the texture as byte [], then your json will contain the name or url of byte [].
{
"id": 1,
"title": "Steel Gloves",
"value": 222,
"toolTip": "This is steel gloves",
"stackable": true,
"category": "weapon",
"slug": "steel_gloves",
"sprite": "steelgloves"
}
Then when you grab the json you convert to C # and look for the byte array. Once you have an array of bytes, you can restore the sprite:
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));
source to share
If you are using JsonUtility
serialization, you can implement ISerializationCallbackReceiver
to receive serialization callbacks. This way you can load the correct sprite based on the saved path after the object is deserialized. You will also avoid duplicating resources.
[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() { }
(...)
}
If you really want to store the sprites directly in JSON, consider serializing the raw texture data taken from Sprite.texture.GetRawTextureData()
(probably store the binary data in a base64 string ) and recreate it at runtime with Sprite.Create()
. A trick applies here as well ISerializationCallbackReceiver
.
As a side note, if it suits your needs, be sure to consider dropping the JSON based object database in favor of using Scriptable Objects . This way, you can easily reference UnityEngine objects without having to use the Resources folder (which is not recommended if necessary).
source to share