Search Unity

Saving ScriptableObjects with non-serialized fields through code

Discussion in 'Scripting' started by dls7470, Jul 31, 2018.

  1. dls7470

    dls7470

    Joined:
    Jul 31, 2018
    Posts:
    3
    I have a class that inherits from ScriptableObject with a few fields that can't be serialized and one that can be. In another script I create an instance of the ScriptableObject, set all of its fields and then save it using UnityEditor.AssetDatabase.CreateAsset(string path). I have a final script with a serialized field of the ScriptableObject.

    When adding the newly saved ScriptableObject to the third script and attempting to read data from it, the List and the Dictionary are both set to null, while the Sprite retains the value it was set to.

    Is there any way to save the List and Dictionary to the .asset file?

    My code is as follows:
    Code (CSharp):
    1. public class MyScriptableObject : ScriptableObject
    2. {
    3.     public Dictionary<string, Sprite> sprites;
    4.  
    5.     public Sprite sprite;
    6. }
    Code (CSharp):
    1. MyScriptableObject myObject = (MyscriptableObject)ScriptableObject.CreateInstance("MyScriptableObject");
    2.  
    3. Dictionary<string, Sprite> sprites = new Dictionary<string, Sprite>();
    4.  
    5. //loadedSprites is a [SerializeField] List<Sprite> present in this class
    6. for(int i = 0; i < loadedSprites.Cout; i++)
    7. {
    8.     sprites[i + ""] = loadedSprites[i];
    9. }
    10. myScriptableObject.sprites = sprites;
    11.  
    12. myScriptableObject.sprite = loadedSprites[0];
    Code (CSharp):
    1. //loadedMyScriptableObject is a [SerializeField] MyScriptableObject present in this class
    2. //and I drag the saved asset onto this script
    3.  
    4. //when this code is run, loadedMyScriptableObject.sprites is null,
    5. //but loadedMyScriptableObject.sprite is what it was set to in the previous code
    6. List<Sprites> sprites = loadedMyScriptableObject.sprites;
    7. Sprite sprite = loadedMyScriptableObject.sprite;
     
  2. dls7470

    dls7470

    Joined:
    Jul 31, 2018
    Posts:
    3
  3. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,537
    Well as you said dictionary isn't serialized, so it's not getting saved to the asset. That's what being serialization does, it serializes the data into something that can be written to disk.

    Furthermore, in your 3rd piece of code you say:
    Code (csharp):
    1. List<Sprites> sprites = loadedMyScriptableObject.sprites;
    This doesn't make sense, 'MyScriptableObject.sprites' is a Dictionary<string, Sprite>, not a List<Sprites> (Sprites isn't even a known type as far as defined here). This line of code shouldn't work at all.
     
  4. dls7470

    dls7470

    Joined:
    Jul 31, 2018
    Posts:
    3
    So in order to be able to save the data I will just have to use a different data structure?

    That line was just a mistake, I meant for it to be
    Code (CSharp):
    1. Dictionary<string, Sprite> sprites = loadedMyScriptableObject.sprites;
    I've obviously already fixed that, but not my problem.
     
  5. samizzo

    samizzo

    Joined:
    Sep 7, 2011
    Posts:
    487
    To serialise a
    Dictionary
    you can implement the
    ISerializationCallbackReceiver
    interface and serialise the keys and values yourself. The documentation has an example of this. It's fairly straightforward.

    Sam
     
    Last edited: Aug 1, 2018
  6. SteveSmithSoftware

    SteveSmithSoftware

    Joined:
    Mar 23, 2014
    Posts:
    197