Search Unity

Saving Items (ScriptableObject)

Discussion in 'Scripting' started by gegebel, Apr 6, 2018.

  1. gegebel

    gegebel

    Joined:
    Jan 29, 2014
    Posts:
    469
    Hello folks,

    I have an Item script

    Code (CSharp):
    1. [System.Serializable]
    2.     public abstract class Item : ScriptableObject, IMoveable
    3.     {
    4.         [SerializeField]
    5.         private Sprite icon;
    6.  
    7.         [SerializeField]
    8.         private int stackSize;
    9.  
    10.         private Slot slot;
    11.  
    12.         public Sprite MyIcon
    13.         {
    14.             get
    15.             {
    16.                 return icon;
    17.             }
    18.         }
    19.  
    20.         public int MyStackSize
    21.         {
    22.             get
    23.             {
    24.                 return stackSize;
    25.             }
    26.         }
    27.  
    28.         public Slot MySlot
    29.         {
    30.             get
    31.             {
    32.                 return slot;
    33.             }
    34.  
    35.             set
    36.             {
    37.                 slot = value;
    38.             }
    39.         }
    40.  
    41.         public void Remove()
    42.         {
    43.             if (MySlot != null)
    44.             {
    45.                 MySlot.RemoveItem(this);
    46.             }
    47.         }
    48.     }
    usually when using [System.Serializable] it works when I save using a BinaryFormatter.

    Since Item inherits from ScriptableObjects, it won't work. So far so good.
    After reading a bit, I stumbled into lots of informations but none was really clear.

    From what I understood you have to create an instance using ScriptableObject.CreateInstance().
    How do I use it and where ?

    I use the Editor to create my items though, that should be instances right?

    Code (CSharp):
    1. [CreateAssetMenu(fileName = "Nettle", menuName = "Items/Plants/Nettle", order = 3)]
    2.     public class Nettle : Item, IUseable
    3.     {
    4.         public void Use()
    5.         {
    6.  
    7.         }
    8.     }
    How do I save my items now?
     
  2. Nigey

    Nigey

    Joined:
    Sep 29, 2013
    Posts:
    1,122
    Hey gegebel,

    'Creating an instance' is a bit of a dangerous term that Unity uses when it comes to ScriptableObjects, as we associate instantiation to runtime generation. When you right click in any folder in the project window and navigate too "Items/Plants/Nettle" and create that ScriptableObject. You now have your saved asset. That acts like any other asset in your 'Assets' folder, like a 3d model, texture, or material. It works basically the same way. You can drag and drop it into a prefab's field for use in the scene. When you do, you're not playing with an instance of that ScriptableObject that's been created at runtime. You're playing with that direct reference. Like you would if you had dragged a material into a prefab's field in the inspector.

    P.S - Clean code :).
     
  3. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,713
    If you want to save something like your inventory, so it can be reloaded, I would suggest that you save only what you need to reproduce it. For instance, the item (by name, or number), the stack size, and the slot #.
    With those 3 values, you should be able to reload your inventory.

    If you meant something else, please explain. :)
     
    Nigey likes this.
  4. gegebel

    gegebel

    Joined:
    Jan 29, 2014
    Posts:
    469
    I thought I could save the instance of an item. For example, I have different bags. They are the same item but can have different sizes. So one instance differs from the other.

    just saving a name and so on is not enough.

    I'm no expert in ScriptableObjects but since I generate the items at runtime, for example for loot, I'd want to actually save the exact item I instanciated.

    Example:
    I kill a monster, it is supposed to drop a sword.This sword could have a bonus on it like +1 or +2 and so on. All decided randomly at runtime.
    I instantiate the sword, determine its bonus, and drop it in worldspace. The player puts it in his inventory. How can I save this exact sword ?

    Sorry I can't explain much better.
     
  5. Nigey

    Nigey

    Joined:
    Sep 29, 2013
    Posts:
    1,122
    There'll be other/better methods out there, but I'd probably stick to something relatively simple. Potentially a JSON serializer/deserializer. You'd just need to think about what exactly you want to break down into it's data. JSON now works alongside Monobehaviours, and allows you to override their existing data with a JSON. That sounds like what you want to do.

    https://docs.unity3d.com/Manual/JSONSerialization.html
    https://docs.unity3d.com/ScriptReference/JsonUtility.html
    https://docs.unity3d.com/ScriptReference/JsonUtility.FromJsonOverwrite.html

    FYI - JSONUtility (Unity's JSON serializer) supports inheritance: https://answers.unity.com/questions/1109403/how-does-jsonutilityfromjson-handle-inheritance.html.
     
    Last edited: Apr 6, 2018
unityunity