The board administrator and developer will be on vacation until the end of July. Therefore replies will be slower than usual.

Serialiazing and Deserializing Custom Items

Bombastrelopas
Posts: 2
Joined: Mon Jun 19, 2017 7:57 am

Serialiazing and Deserializing Custom Items

Postby Bombastrelopas » Mon Jun 19, 2017 9:27 am

Hello I have been trying to serialize a custom Item type I have created in Inventory pro with not much luck. My tries so far:

Code: Select all

        //Use this as a default ability item
        InventoryItemBase item = Object.Instantiate(m_DefaultItemPrefab.GetComponent<InventoryItemBase>());
        InventoryItemBase item2 = Object.Instantiate(m_DefaultItemPrefab2.GetComponent<InventoryItemBase>());

        //Name: Serialization with items
        string serialized = JsonSerializer.Serialize( item , null );
        Debug.Log(serialized);
        JsonSerializer.DeserializeTo( item2 , serialized , null );

This gives me the error :
Couldn't deserialize type Devdog.InventoryPro.InventoryItemBase - Object type UnityEngine.AudioClip cannot be converted to target type: UnityEngine.GameObject

But the string seems to be OK:
{"audioClipWhenUsed":{"audioClip":0,"volume":1.0,"pitch":1.0,"loop":false},"AbilityTest":1,"AbilityShootAnimation":0,"index":0,"itemCollection":null,"_id":3,"_name":"Shield(duplicate)0","_description":"Activating it does nothing! <b>So cool >_> </b>.","_category":2,"_useCategoryCooldown":false,"_overrideDropObjectPrefab":0,"_icon":3,"_layoutSizeCols":1,"_layoutSizeRows":1,"_weight":0.0,"_requiredLevel":0,"_rarity":4,"_stats":[{"_stat":5,"value":"30","isFactor":false,"actionEffect":0}],"_usageRequirement":[],"_buyPrice":{"parentGroup":null,"_currency":null,"_amount":0.0},"_sellPrice":{"parentGroup":null,"_currency":null,"_amount":0.0},"_isDroppable":true,"_isSellable":true,"_isStorable":true,"_maxStackSize":1,"_cooldownTime":5.0,"$type":"Devdog.InventoryPro.SkillExampleInventoryItemType"}
Another try I did:

Code: Select all

        var serializationModel = new CustomAbilitySerializationModel(item);
        var serializationModel2 = new CustomAbilitySerializationModel(item2);
        string serialized = JsonSerializer.Serialize( new List<CustomAbilitySerializationModel> {serializationModel , serializationModel2} , null );
        Debug.Log(serialized);

Which gives me this string [{"weight":0.0,"weaponEn":4,"TestOffensiVeAbility":0,"itemID":1,"amount":2,"stats":[{"statID":3,"value":"30","actionEffect":0,"isFactor":false}],"collectionName":""},{"weight":0.0,"weaponEn":4,"TestOffensiVeAbility":1,"itemID":1,"amount":2,"stats":[{"statID":0,"value":"20","actionEffect":0,"isFactor":false}],"collectionName":""}]
The thing is I don't know how/if i can use this to then create an item during runtime. The correct one to me it seems would be the first one but it get's me this weird error.
So all in all what I want is to serialize my custom item (created at runtime) and then deserialize the values to another item(like in the first block of code). Any ideas what I am doing wrong?
And also another important question: Why my TestOffensiveAbility is serialized like a number? ("TestOffensiVeAbility":0). Shouldn't it be using the GUID of the scriptable object used for this ability? (Code reference of the scriptable object below):

Code: Select all

public class BattleAbility : ScriptableObject {

    public float ActivationTime;

}

Thanks in advance for any help.

User avatar
PeterBibinin
Posts: 178
Joined: Mon Oct 24, 2016 10:55 pm

Re: Serialiazing and Deserializing Custom Items

Postby PeterBibinin » Mon Jun 19, 2017 11:56 pm

I don't know much about serialization but look in SaveLoad script provided somewhere in InventoryPro there is serialization used and also with Easy Save Integration. Maybe there you can find answer to your question.
Waiting for sunrise
----------------------------------------------
Try make world beter ;]
----------------------------------------------
BAZINGA !

Bombastrelopas
Posts: 2
Joined: Mon Jun 19, 2017 7:57 am

Re: Serialiazing and Deserializing Custom Items

Postby Bombastrelopas » Tue Jun 20, 2017 8:32 am

I don't know much about serialization but look in SaveLoad script provided somewhere in InventoryPro there is serialization used and also with Easy Save Integration. Maybe there you can find answer to your question.

Thanks for the tip. I took a look at it but I think this solution is a more generic one which doesn't really help my case (where my Items are created at runtime).
A small Update on my problem:
I have managed to properly serialize my object so it doesn't give me just a weird number anymore and it now properly serializes the sub-attributes of the object (code below):

Code: Select all

public class BattleAbility : ScriptableObject , ISerializationCallbackReceiver {

    [SerializeField]
    public float ActivationTime;

    [SerializeField] public string TestString = "This is a test";

    [SerializeField]
    [IgnoreCustomSerialization] // Ignore in custom serializer - Let unity seriarlize this.
    private string _serializedJsonString = "{}";

    [SerializeField]
    [IgnoreCustomSerialization] // Ignore in custom serializer - Let unity seriarlize this.
    private List<UnityEngine.Object> _objectReferences;


    private readonly BetterSerializationModel _serializer = new BetterSerializationModel();

    public virtual void Save()
    {
        _serializer.Save(ref _objectReferences, ref _serializedJsonString, this);
    }

    public virtual void Load()
    {
        _serializer.Load(ref _objectReferences, ref _serializedJsonString, this);
    }

    public void OnBeforeSerialize()
    {
        Save();
    }

    public void OnAfterDeserialize()
    {
        Load();
    }
}

Now when I write to json my string is as follows:
{"items":[{"Name":"Shield","Description":"Activating it does nothing! <b>So cool >_> </b>. (this item was created from json).","StatDecorator":[{"_stat":0,"value":"30","isFactor":false,"actionEffect":0}],"TestAbility":{"ActivationTime":1.0,"TestString":"This is a test"},"Cooldown":5.0,"itemID":0,"amount":0,"stats":[],"collectionName":null},{"Name":"NewRevolver","Description":"RevolverTest (this item was created from json).","StatDecorator":[{"_stat":1,"value":"20","isFactor":false,"actionEffect":0}],"TestAbility":{"test":0,"AbilityWeapon":1,"ActivationTime":1.5,"TestString":"This is a test"},"Cooldown":1.0,"itemID":0,"amount":0,"stats":[],"collectionName":null}]}
The above json is me serializing a custom SerializationModel I have made which contains an array of 2 CustomItemSerializationModels(so the above output is 2 items). Code below:

This is loading 2 prefab InventoryItems making a serializationModel for each one of them and then serializing the Mix of the 2.

Code: Select all

    public void WriteJson()
    {
        //Use this as a default ability item
        InventoryItemBase item = Object.Instantiate(m_DefaultItemPrefab.GetComponent<InventoryItemBase>());
        InventoryItemBase item2 = Object.Instantiate(m_DefaultItemPrefab2.GetComponent<InventoryItemBase>());

        //TODO(JohnMir): Now items are created from a prefab. On next tests make them from a List of <inventoryItem>
        var serializationModel = new CustomAbilitySerializationModel(item);
        var serializationModel2 = new CustomAbilitySerializationModel(item2);
        var serializationModelMix = new MySuperItemCollectionSerializer( new List<CustomAbilitySerializationModel>() { serializationModel , serializationModel2 } );
        string serialized = JsonSerializer.Serialize( serializationModelMix , null );
        Debug.Log(serialized);
        StreamWriter writer = new StreamWriter(JsonPath , true);
        writer.WriteLine(serialized);
        writer.Close();
       
    }

    public void ReadJson()
    {
        StreamReader reader = new StreamReader(JsonPath);
        string deserializedData = reader.ReadToEnd();
        Debug.Log(deserializedData);
        var returningSerializationModel = new MySuperItemCollectionSerializer( new List<CustomAbilitySerializationModel>());
        JsonSerializer.DeserializeTo(returningSerializationModel , deserializedData, null);

        //Create a skill for each item in the CollectionSerializer
        foreach( var sm in returningSerializationModel.items )
        {
            GenerateSkillFromSerializationModel( sm );
        }

    }

This is my CustomAbilitySerializationModel:

Code: Select all

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Devdog.InventoryPro;
using Devdog.General.ThirdParty.UniLinq;
using Object = UnityEngine.Object;

[System.Serializable]
public class CustomAbilitySerializationModel : InventoryItemSerializationModel
{
    //Stats we want to pass concerning our ability
    public string Name;
    public string Description;
    public StatDecorator[] StatDecorator;
    [SerializeField]
    public BattleAbility TestAbility;
    //public Sprite AbilityIcon;
    public float Cooldown;

    public CustomAbilitySerializationModel()
    {
    }

    public CustomAbilitySerializationModel(InventoryItemBase item)
    {
        FromItem(item);
    }

    public override void FromItem(InventoryItemBase item)
    {
        if (item == null)
        {
            this.itemID = -1;
            this.amount = 0;
            this.collectionName = string.Empty;
            this.stats = new StatDecoratorSerializationModel[0];

            return;
        }
        this.Name = item.name;
        this.Description = item.description + " (this item was created from json).";
        this.StatDecorator = item.stats;
        //this.AbilityIcon = item.icon;
        this.Cooldown = item.cooldownTime;
        SkillExampleInventoryItemType itemOf = (SkillExampleInventoryItemType)item;
        this.TestAbility = itemOf.AbilityTest;
//        this.TestAbility = Resources.Load( "Battle/B" ) as BattleAbility; //TEST
        //NOTE(JohnMir): These probably not needed
        //this.itemID = 1;//NOTE: Doesn't matter will be fixed when reimported anyway
        //this.collectionName = item.itemCollection != null ? item.itemCollection.collectionName : string.Empty;
        //this.stats = item.stats.Select(o => new StatDecoratorSerializationModel(o)).ToArray();

    }

    public override InventoryItemBase ToItem()
    {
        InventoryItemBase inst = Object.Instantiate( ItemManager.database.items[ 1 ] );
        /*
        List<InventoryItemBase> temp = new List<InventoryItemBase>(RuntimeItemCreator.Instance.crudList.ToArray());
        test.description = "Hey";
        temp.Add(test);
        RuntimeItemCreator.Instance.crudList = temp;

        if (itemID < 0 || itemID > ItemManager.database.items.Length - 1)
        {
            Debug.Log("Problem");
//                DevdogLogger.LogWarning("ItemID is out of range, trying to deserialize item " + itemID);
            return null;
        }

        //TODO: This get's the item exactly from database need to create new item here and get it from there?

        var item = ItemManager.database.items[itemID]; //HERE
        var inst = UnityEngine.Object.Instantiate<InventoryItemBase>(item);//Remove this
        var s = this.stats.Select(o => o.ToStat()).ToArray(); //Keep this

        inst.currentStackSize = amount; //Make it 1
        inst.stats = s; //Keep
        if (string.IsNullOrEmpty(collectionName) == false)
        {
            inst.itemCollection = ItemCollectionBase.FindByName(collectionName); //Keep
        }
        */

        return inst;
    }
}

And this is the thing that's put into the serializer:

Code: Select all

using System;
using System.Collections.Generic;
using Devdog.General.ThirdParty.UniLinq;
using System.Text;
using Devdog.General;
using UnityEngine;

namespace Devdog.InventoryPro
{
    [System.Serializable]
    public class MySuperItemCollectionSerializer
    {
        public CustomAbilitySerializationModel[] items;

Now my current problem comes when I try to deserialize the serialized string output. It get's me this error(which looks a bit like the error on my first post when i tried to deserialize an item:
Unable to cast <{"ActivationTime":1.0,"TestString":"This is a test"}> (with type = System.Collections.Generic.Dictionary`2[System.String,Devdog.General.ThirdParty.FullSerializer.fsData]) to type System.Int64
at Devdog.General.ThirdParty.FullSerializer.fsData.Cast[Int64] () [0x00065] in C:\Users\ioann\Documents\tera-west\Assets\Devdog\General\ThirdParty\FullSerializer\Source\fsData.cs:276


Return to “Programming”

Who is online

Users browsing this forum: Yahoo [Bot] and 1 guest