Saving scriptable object that was changed in edit mode by script

Hi!

So, my SO only has one variable, Material[ ][ ], and i need to make it not reset after quiting unity. The value of this array won’t change after build.

Am i missing something obvious?

Unity cannot serialize jagged or multidimensional arrays. One thing you could do is use a list or array of a class that contains an array.

public class MySo : ScriptableObject
{
    public MaterialArray[] MaterialArrays;
}

[System.Serializable]
public class MaterialArray
{
    public Material[] Mats;
}
1 Like

Thanks! I’ll try that later!

After taking a closer look at this script i noticed that it doesn’t solve my main problem. I still need a way to save changes made by my script.

Are you trying to save data between play sessions? ScriptableObjects won’t do this for you. They are essentially static assets like a Texture or an audio file. You can change them during runtime but the changes will only persist as long as your game is running. If you want to save data between play sessions you will need to create a saved game system.

1 Like

What @PraetorBlue writes above is correct, but only if you’re talking about your runtime game script making changes. Those cannot be saved in the build. For that you need a savegame system of some kind. ScriptableObjects are like read-only databases that go out into your build.

If instead you have an Editor script, something that is intended to change data in the scriptable object and have it serialize to disk in your project, you have to tell Unity that it is dirty and needs saving.

This is accomplished using the Undo system, specifically Undo.RecordObject():

https://docs.unity3d.com/ScriptReference/Undo.RecordObject.html

Conveniently this also ensures you can undo stuff your editor scripts change.

1 Like

It works more like saving current materials of game objects. After i click a button in the inspector, script gets all materials from selected game objects and applies it to Material[ ][ ]. After i do this for every position in the array, the value won’t change for the rest of the game. Everything happens in edit mode

1 Like

Ah, excellent. You’re on the right track, check my post above.

1 Like

This might be what i am looking for! I’ll check that tomorrow tho

Am i doing this the right way? It doesn’t save. In documentation it says that: “The changed properties are recorded on the undo stack.”. Maybe i need another function to save what was recorded?

Edit: I found this function in documentation https://docs.unity3d.com/ScriptReference/EditorUtility.SetDirty.html. Since i am not changing scene objects this could work (?). What do you think about this?

Edit2: EditorUtility.SetDirty() worked! It saved string changed by script. I’ll try the same thing for Material[ ][ ].

Edit3: Sadly, unity cannot serialize multidimensional arrays. Instead i’ll use WarmedxMints answer

    public static void RecordFrame(FloorAnimation anim, int frame, MeshRenderer[] tiles)
    {
        List<Material> materials = new List<Material>();

        foreach (MeshRenderer t in tiles)
            materials.Add(t.sharedMaterial);

        Undo.RecordObject(anim, "Recorded frame in " + anim.name + " at " + frame + " frame");
        anim.test = "Recorded";
        //anim.animation[frame] = materials.ToArray();
    }

WarmedxMints, Kurt-Dekker and PraetorBlue. thank you guys so much! Everything is working! <3

1 Like

TEAMWORK! Yeah!!! Go forth @hLLwx and take it away!

1 Like