SaveID/GUID on non-monobehavior class

Hey!

I would appreciate any ideas on how can I implement SaveID/GUID like behavior on non-mono class.
For example something like

    [System.Serializable]
    public class Item
    {
        public string SaveID;
    }

    public class Inventory: MonoBehaviour
    {
        public List<Item> InventoryItems = new List<Item>();
    }

and I want SaveID on Item to be automatically populated if it’s empty. And I want prefab instances to have unique ID’s from Prefab.

Now I tried using Serialization Callbacks like

        public void OnBeforeSerialize()
        {
            if (SaveID.Length == 0)
            {
                SaveID = System.Guid.NewGuid().ToString();
            }
        }

But, then I’m unable to mark the object and prefab instance dirty if I do this inside Item class. So what happens is that when the game is run, the SaveID reverts to prefab values.

Has anyone tried something like this?

Your class must inherit from the ISerializationCallbackReceiver interface for you to have OnBeforeSerialize() called.

[System.Serializable]
public class Item : ISerializationCallbackReceiver 
{
    public string SaveID;

    public void OnBeforeSerialize()
    {
        if (SaveID.Length == 0)
        {
            SaveID = System.Guid.NewGuid().ToString();
        }
    }

}

Thank you, but the problem with this approach is that if this happens on an instance of the prefab, it’s not marked as dirty. So unity won’t serialize it and when I hit play the value reverts to that of a master prefab.

And I can’t call SetDirty or RecordUndo functions because i have no reference to mono-behavior via non-mono class.

The serialization you are trying to interrupt to modify data is the automatic scene/prefab serialization that occurs on monobehaviours, so as you suspected, it is the monobehaviour you have to mark dirty. I did not realize you would need to do that. I suggest you move the ISerializationCallbackReceiver to the Inventory monobehaviour class, loop through the list of Items and update their data, them use a SerializedObject to mark the monobehaviour dirty. Keep in mind SerializedObject is a member of the UnityEditor namespace, so it will not compile unless you protect it with UNITY_EDITOR flags.

This is what I think it should look like. I haven’t done this before but I have done similar things with SerializedObject, so hopefully it works.

[System.Serializable]
public class Item
{
    public string SaveID;
}

public class Inventory : MonoBehaviour, ISerializationCallbackReceiver
{
    public List<Item> InventoryItems = new List<Item>();

    public void OnBeforeSerialize()
    {
        foreach (Item curItem in InventoryItems)
        {
            if (curItem.SaveID.Length == 0)
            {
                curItem.SaveID = System.Guid.NewGuid().ToString();
            }
        }

#if UNITY_EDITOR
        UnityEditor.SerializedObject sObj = new UnityEditor.SerializedObject(this);
        sObj.Update();
        sObj.ApplyModifiedProperties();
#endif
    }

    public void OnAfterDeserialize()
    {

    }

}

Thank you! I’ll try this.