1
votes

So I created a JSON script to serialize and save the inventory of a game in Unity, the saving of the inventory items names, stats etc works fine but the icon of the item does load properly, I get a placeholder icon with "?" instead.

I have been following: Is it possible to serialize sprites in unity?

but this led to the error mentioned above.

saving and loading is done with the following:

public class JSONsave 
{

[SerializeField]
Sprite m_InSprite;

SerializeTexture exportObj = new SerializeTexture();
SerializeTexture importObj = new SerializeTexture();

[ContextMenu("serialize")]
public void SerializeTest(CharacterStats PlayerStats)
{
    PlayerSaveData data = new PlayerSaveData(PlayerStats);
    string text = JsonUtility.ToJson(data);
    File.WriteAllText(Application.persistentDataPath + "/playerInfo.dat", text);
}

[ContextMenu("deserialize")]
public PlayerSaveData DeSerializeTest()
{
    string text = File.ReadAllText(Application.persistentDataPath + "/playerInfo.dat");
    //importObj = JsonUtility.FromJson<SerializeTexture>(text);
    PlayerSaveData data = JsonUtility.FromJson<PlayerSaveData>(text);
    return data;
}

[Serializable]
public class SerializeTexture
{
    [SerializeField]
    public int x;
    [SerializeField]
    public int y;
    [SerializeField]
    public byte[] bytes;
}
}

converting the item to a serializable is done with:

 [Serializable]
public class SaveGameEquipment
{
public string name;

[SerializeField]
Sprite m_InSprite;

public bool isDefaultItem;

public EquipmentSlot equipSlot;
public SkinnedMeshRenderer mesh;
public int armorModifier;
public int damage;
public int energy;

SerializeTexture exportObj = new SerializeTexture();


public SaveGameEquipment(Equipment a_item)
{
    //get items sprite
    m_InSprite = a_item.icon;
    //converting sprite to json readable format - 
    Texture2D tex = m_InSprite.texture;
    exportObj.x = tex.width;
    exportObj.y = tex.height;
    exportObj.bytes = ImageConversion.EncodeToPNG(tex);

    name = a_item.name;
    equipSlot = a_item.equipSlot;
    mesh = a_item.mesh;
    armorModifier = a_item.armorModifier;
    damage = a_item.damage;
    energy = a_item.energy;
    isDefaultItem = a_item.isDefaultItem;



}

public class SerializeTexture
{
    [SerializeField]
    public int x;
    [SerializeField]
    public int y;
    [SerializeField]
    public byte[] bytes;
}

Finally Loading the item back is done with the following:

public void loadItems(PlayerSaveData data)
{

    SaveGameItem.SerializeTexture importObj = new SaveGameItem.SerializeTexture();

    foreach (SaveGameEquipment item in data.wrappedList)
    {
        Equipment n_Item = ScriptableObject.CreateInstance<Equipment>();
        n_Item.name = item.name;

        //sort out the icon
        Texture2D tex = new Texture2D(importObj.x, importObj.y);
        ImageConversion.LoadImage(tex, importObj.bytes);
        Sprite mySprite = Sprite.Create(tex, new Rect(0.0f, 0.0f, tex.width, tex.height), Vector2.one);
        //GetComponent<Equipment>().sprite = mySprite;

        n_Item.icon = mySprite;


        n_Item.equipSlot = item.equipSlot;
        n_Item.mesh = item.mesh;
        n_Item.armorModifier = item.armorModifier;
        n_Item.damage = item.damage;
        n_Item.energy = item.energy;

        n_Item.isDefaultItem = item.isDefaultItem;

        Add(n_Item);
    }
}

In the above including the GetComponent gives me an ArgumentException as the "Equipment" is a scriptable object and does not derive from MonoBehaviour.

Thank you in advance for any help resolving this

1
fyi there is a game dev stackexchange gamedev.stackexchange.comkei

1 Answers

0
votes

You would be better off using an ID for the item icon and you could have a dictionary to store icons and their respective IDs. Serializing and storing copies of the item icons is just unnecessary. Try something like this:

public static Dictionary<int,Texture> itemIcons = new Dictionary<uint, itemIcons>();

public void loadIcons(){
    // Initialize your dictionary with your icons
    itemIcons.Add(id,texture);
    ...
}

public void loadItems(PlayerSaveData data)
{

    SaveGameItem.SerializeTexture importObj = new SaveGameItem.SerializeTexture();

    foreach (SaveGameEquipment item in data.wrappedList)
    {
        Equipment n_Item = ScriptableObject.CreateInstance<Equipment>();
        n_Item.name = item.name;

        //sort out the icon
        Texture2D tex = itemIcons[item.iconID];
        Sprite mySprite = Sprite.Create(tex, new Rect(0.0f, 0.0f, tex.width, tex.height), Vector2.one);
        //GetComponent<Equipment>().sprite = mySprite;

        n_Item.icon = mySprite;


        n_Item.equipSlot = item.equipSlot;
        n_Item.mesh = item.mesh;
        n_Item.armorModifier = item.armorModifier;
        n_Item.damage = item.damage;
        n_Item.energy = item.energy;

        n_Item.isDefaultItem = item.isDefaultItem;

        Add(n_Item);
    }
}

If it's easier for you, you could also store the items in an array like this:

[SerializeField]
Texture[] itemIcons;

So that you could assign the icons in the inspector.