Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

ScriptableObject instance gives a "type mismatch" when referenced in an SO asset

Discussion in 'Scripting' started by Wolfeur, Apr 27, 2020.

  1. Wolfeur

    Wolfeur

    Joined:
    Feb 11, 2020
    Posts:
    3
    I have an Inventory ScriptableObject, made into an asset, in which there is a List of InventorySlot (also a SO), but the slots are Instantiated when an Item is picked up.

    When I look at the Inventory with the editor, the generated slots show "type mismatch" when instantiated, but beyond that they actually work fine. When exiting play mode, then slots are now shown as "missing" and the whole thing breaks.

    I don't really understand how serialization and instantiation works for SO; why do the type not match (when a slot is made as an asset and linked manually it works fine), and why isn't the instantiated slot kept in memory even though the inventory itself is serialized?

    Thanks in advance.
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,971
    One possible cause: If you change the type of a serialized Unity reference without changing the name of the variable this will cause problems. The reason is the type gets serialized as well as the value, and when you change the code, it won't deserialize properly. One solution is to rename the field to something else, or just recreate the asset from scratch.
     
  3. StaggartCreations

    StaggartCreations

    Joined:
    Feb 18, 2015
    Posts:
    2,141
    I've gotten around this by using a private list (which serializes properly), combined with a public property.

    Code (CSharp):
    1. [SerializeField]
    2. private List<HierarchyObject> _objects = new List<HierarchyObject>();
    3. public List<HierarchyObject> objects
    4. {
    5.      get { return _objects; }
    6.      set { _objects = value; }
    7. }
    In my case, HierarchyObject is also derrived from ScriptableObject. So I suppose this'll also work for you as well.

    Note that if you save a ScriptableObject to an asset file, other ScriptableObjects serialized in it must also be saved to a file. This is the nature of Unity's serialization apparently. This means your InventorySlot instances also need to be an asset file. You can also save this as sub-assets of your Inventory ScriptableObject, and have the List reference these sub-assets instead, like so:

    Code (CSharp):
    1. string assetPath = AssetDatabase.GetAssetPath(<inventory instance>);
    2. Object file = AssetDatabase.LoadAssetAtPath(assetPath, typeof(Inventory));
    3.  
    4. InventorySlot slot = ScriptableObject.CreateInstance<InventorySlot>();
    5. AssetDatabase.AddObjectToAsset(slot, file);
    6. //Add to list
    I've had a run in with the same issue last week, and this setup seems to work as expected.

    Problem in your case is that you can't do this at runtime. This is unfortunately the case where you'd have to consider saving data to JSON or XML files, which simply comes down to writing data to a file. An alternative would be to create a bunch of empty InventorySlot subassets beforehand, and simply modify them at will.
     
  4. Wolfeur

    Wolfeur

    Joined:
    Feb 11, 2020
    Posts:
    3
    Thanks for the idea, but unfortunately it didn't fix my issue.

    That's a strange limitation, I wonder why that is. Problem is that I don't want to store hundreds of assets for each item and slot for all containers that could exist. I assume then that the only thing I can do is make all those things simple serializable classes, but then I'll need a "wrapper class" as scriptableobject of some sort for items so that I still have typical items available as assets. I was hoping I could make a class inheriting from both Item and ScriptableObject, but it seems not doable. Would you have any idea?

    I'm trying to imitate this model logic but that makes a lot of scriptableobjects within scriptableobjects, and while that should work fine for static item data, it's not great for instantiated systems. Just having durability already forces instantiation of some sort and I'm trying to have items be a bit modular.

    Edit: I'm just wondering if it would be possible to keep Item as a SO but also have it serialize normally, in the inspector and in a save file. Do you know whether that's doable?
     
    Last edited: Apr 28, 2020
  5. tylorc

    tylorc

    Joined:
    Jul 22, 2018
    Posts:
    3
    Hey Wolfeur, I know this post is from a long time ago but I'm just curious if you ever resolved this issue? I believe I am in your 2020 shoes right now.