Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Saving Scriptable Objects[SOLVED]

Discussion in 'Editor & General Support' started by renman3000, Sep 7, 2018.

  1. renman3000

    renman3000

    Joined:
    Nov 7, 2011
    Posts:
    6,697
    Hi there,
    I just started using Scriptable Objects in Unity, however it is not saving.

    I see I should use EditorUtility.SetDirty() or AssetDatbase.SaveAssets(), but I am unclear as to how to apply either.

    Any help would be appreciated.
    Thanks
     
  2. samizzo

    samizzo

    Joined:
    Sep 7, 2011
    Posts:
    487
    If you have a custom EditorWindow where you are modifying your
    ScriptableObject
    you just need to make sure that
    EditorUtility.SetDirty(obj);
    is called when you make changes to it. Unity will save it when you select File > Save Project.

    If you are just using the default inspector to edit your object then Unity will automatically mark it dirty. If you have written a custom inspector then you should use SerializedObject and SerializedProperty to modify it. That will automatically handle flagging the object as dirty.

    You shouldn't have to call SaveAssets unless you want to explicitly save.

    If you're still having problems it would help if you could create a minimal reproducible example that shows the issue.

    Sam
     
    Vorrin, honor0102, binga_ and 5 others like this.
  3. renman3000

    renman3000

    Joined:
    Nov 7, 2011
    Posts:
    6,697

    Hi Sam,
    Thanks.

    I am not using a custom Editor Window, at least I think.
    This is my set up after using this video by Board to Bits Games as my reference point (
    ).


    1) via this link: http://wiki.unity3d.com/index.php?title=CreateScriptableObjectAsset, I have a ScriptableUtilityObject.cs, this makes it easy to create, name and place unique new ScriptableObject asset files.

    2) also via the same link I have RaceDataAsset, in which is used as a menu item to create a RaceData object.

    3) I then have the script RaceData. This script holds two lists, which I modify in game play, if isRecording is true. If isRecording is false, the system gathers the raceData object, values and uses them accordingly.

    So, where I am is, that I can indeed record the values and adjust the raceData lists, as desired, via game play. I can play back those values, when not recording (!isRecording). However, where the issue is, is if I quit, the data of raceData object, is lost.



    I am not sure how this applies to what you have suggested, any help is appreciated. A friend has pointed me to this, which I am pursuing for now. https://answers.unity.com/questions/831285/can-you-use-a-serializedobject-to-save-game-state.html



    Thanks
     
  4. LaneFox

    LaneFox

    Joined:
    Jun 29, 2011
    Posts:
    7,462
    If you're using the default inspectors then they automatically update any time you change them in the editor, during Play mode or not.
     
  5. renman3000

    renman3000

    Joined:
    Nov 7, 2011
    Posts:
    6,697

    Yes, the issue is, when I quit Unity, the data is lost. I am looking at Json, as potential solution now.
     
  6. LaneFox

    LaneFox

    Joined:
    Jun 29, 2011
    Posts:
    7,462
    If you know what asset what changed then do
    EditorUtility.SetDirty(theAsset);
    and then
    AssetDatabase.SaveAssets();
    and
    AssetDatabase.Refresh();
    .
     
  7. samizzo

    samizzo

    Joined:
    Sep 7, 2011
    Posts:
    487
    Are you trying to use ScriptableObjects to save your game state? It sounds like you are. It sounds like you're trying to modify the ScriptableObject at runtime. Is that correct?

    You can't use ScriptableObjects to do that - they're not designed for saving data at runtime (unless you want to run your game in the editor only).

    That last link you sent has some advice on saving game state which is worth following.

    Sam
     
    Futurristic and renman3000 like this.
  8. renman3000

    renman3000

    Joined:
    Nov 7, 2011
    Posts:
    6,697


    Would one do this with in a MonoDevelop class or in a Scriptable Object class?
    Do those 3 steps all follow in succession? So...
    Code (csharp):
    1.  
    2. void saveData(){
    3. EditorUtility.SetDirty(theAsset);
    4.  AssetDatabase.SaveAssets();
    5. AssetDatabase.Refresh();
    6. }
    7.  
     
    Opeth001 and James-Sullivan like this.
  9. LaneFox

    LaneFox

    Joined:
    Jun 29, 2011
    Posts:
    7,462
    If you modify the SO asset outside of the default inspector then you need to save it this way, afaik. Use this code when you want to save for an SO you modified through code. I used that in my editor inv editor window.
     
    renman3000 likes this.
  10. renman3000

    renman3000

    Joined:
    Nov 7, 2011
    Posts:
    6,697

    hm, ok, away from the computer now. Will test later. Cheers!
     
  11. renman3000

    renman3000

    Joined:
    Nov 7, 2011
    Posts:
    6,697

    Hi,
    So I am confused as how I reach the the point where I can access the "EditorUtility". Let me break down how my set up works, and perhaps you can help me.

    In order for me to create a Scriptable Object, Asset, and manipulate it, I have 4 levels of script. * I included the scripts below for reference.

    1) ScriptableObjectUtility, This makes it easy to create, name and place unique new ScriptableObject asset files.

    2) RaceDataAsset, This allows me to add a component <RaceData>, to a game object from the Menu Window.

    3) RaceData This holds the lists I want to be able to get and set.

    4) RaceMng This is the first MonoDevelop script, in the chain.



    ** So, scripts I can access EditorUtility in are 1) ScriptableObjectUtility and 2) RaceDataAsset. But again, I am unsure as to how I can set any RaceData, if this is the script I want to set to SetDirty, etc.

    Thanks for any help!






    ScriptableObjectUtility
    This makes it easy to create, name and place unique new ScriptableObject asset files.
    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using UnityEditor;
    4. using System.IO;
    5.  
    6. public static class ScriptableObjectUtility
    7. {
    8.     /// <summary>
    9.     //  This makes it easy to create, name and place unique new ScriptableObject asset files.
    10.     /// </summary>
    11.     public static void CreateAsset<T> () where T : ScriptableObject
    12.     {
    13.         T asset = ScriptableObject.CreateInstance<T> ();
    14.  
    15.         string path = AssetDatabase.GetAssetPath (Selection.activeObject);
    16.         if (path == "")
    17.         {
    18.             path = "Assets";
    19.         }
    20.         else if (Path.GetExtension (path) != "")
    21.         {
    22.             path = path.Replace (Path.GetFileName (AssetDatabase.GetAssetPath (Selection.activeObject)), "");
    23.         }
    24.  
    25.         string assetPathAndName = AssetDatabase.GenerateUniqueAssetPath (path + "/New " + typeof(T).ToString() + ".asset");
    26.  
    27.         AssetDatabase.CreateAsset (asset, assetPathAndName);
    28.  
    29.         AssetDatabase.SaveAssets ();
    30.         AssetDatabase.Refresh();
    31.         EditorUtility.FocusProjectWindow ();
    32.         Selection.activeObject = asset;
    33.  
    34.     }
    35.  
    36.     public static void OnDestroy()
    37.     {
    38.  
    39.         Debug.Log("SOU on Destory");
    40.         AssetDatabase.SaveAssets();
    41.  
    42.     }
    43.  
    44.     public static void OnApplicationQuit()
    45.     {
    46.         Debug.Log("SOU on Quit");
    47.         AssetDatabase.SaveAssets();
    48.     }
    49. }
    50.  

    RaceDataAsset
    This allows me to add a component <RaceData>, to a game object from the Menu Window.
    Code (csharp):
    1.  
    2. using System.Collections;
    3. using UnityEngine;
    4. using UnityEditor;
    5.  
    6. public class RaceDataAsset
    7. {
    8.     [MenuItem("Assets/Create/Race Data")]
    9.     public static void CreateAsset()
    10.     {
    11.         ScriptableObjectUtility.CreateAsset<RaceData>();
    12.     }
    13. }


    RaceData
    This holds the lists I want to be able to get and set.
    Code (csharp):
    1.  
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5. using System.IO;
    6. public class RaceData : ScriptableObject {
    7.     public List<Vector2> posList;
    8.     public List<float> rtnList;
    9. }


    RaceMng
    This is the first MonoDevelop script, in the chain.
    Code (csharp):
    1.  
    2. public class RaceMng : MonoBehaviour {
    3. }
    4.  
     
    FMGdev likes this.
  12. LaneFox

    LaneFox

    Joined:
    Jun 29, 2011
    Posts:
    7,462
    You don't need the utility class. Unity has an attribute to handle it.

    Code (csharp):
    1. [CreateAssetMenu(fileName = "Heal", menuName = "Abilities/Heal", order = 0)]
    2.     public class Heal : ScriptableObject
    3.     {
    After it's created then Unity automatically handles all serialization through the default inspector. The only time you need to deal with refreshing the editor assets is if you are modifying the asset file in a different way which in the code you posted you are not so apparently all you are trying to do is create new assets? All you need is the attribute.
     
  13. renman3000

    renman3000

    Joined:
    Nov 7, 2011
    Posts:
    6,697
    Solution was confusing as I could not see how to access EditorUtility from a relevant monodevelop script. That said, here is how.

    Code (csharp):
    1.  
    2.     private void OnDisable()
    3.     {
    4.         #if UNITY_EDITOR
    5.         UnityEditor.EditorUtility.SetDirty(raceData);
    6.         #endif
    7.     }
     
    Arilio19 likes this.