ScriptableObject-Asset resets when not focused in Inspector

Hello,

I’ve got a really strange problem on which I spent a lot of time trying to solve but that I was unable to.

I’ve read through the threads but it seems as no one had the same problem yet. If not, sorry and please post the link for me :slight_smile:
Also I watched this video (Serialization in-depth with Tim Cooper) but it didn’t help me.

So, the problem is as follows:
I’ve a class “PlayerData” that derives from ScriptableObject and I created an .asset file with the script “MakePlayerData”. That all worked fine so far. But when I use it in the game, it only functions if I select the asset and inspect it at runtime. If I don’t do this, the .asset file will loose all it’s content and will be reset.

I use the .asset file as follows:
To get access in an arbitrary class, I just defined a

public PlayerData data;

and referenced it through drag and drop.

To mention: I do an

Application.LoadLevel(int);

but before I update all the information to the referenced .asset file (by accessing the variables directly).
Also, in the exported version it never functions.

Here is the code I talked about:

using UnityEngine;

[System.Serializable]
public class PlayerData : ScriptableObject
{
    // Stats
    public int playerHighScore = 0;
    public int lastPlayerScore = 0;
    public int diamondScore = 0;
    public int emeraldScore = 0;
    public int rubyScore = 0;
    public int goldScore = 0;
    public int silverScore = 0;
    public int bronceScore = 0;
    public int beerScore = 0;
    public int coveredMeters = 0;
    public int lastCoveredMeters = 0;
    public int playerDeaths;
    public int commerceRuneScore = 0;
    public int protectionRuneScore = 0;
    public int metalRuneScore = 0;
    public int thirstRuneScore = 0;
    public int septaRuneScore = 0;
   
    // Runes properties
    public int commerceRuneDuration = 10;
    public int protectRuneDuration = 20;
    public int metalRuneDuration = 10;
    public int thirstRuneDuration = 10;
    public int septaRuneSpawnrate = 20;

    // ElementGeneratorScript's coinProbabilities
    public int[] coinProbabilities = new int[5]{0, 0, 0, 0, 0};
    public void setCoinProbabilities(int[] probabilities)
    {
        for(int i = 0; i < coinProbabilities.Length; i++)
            coinProbabilities[i] = probabilities[i];
    }

    // Shop
    // BasicUpgrades
    public int coinsBUElementItemState = 0;
    public int commerceBUElementItemState = 0;
    public int protectBUElementItemState = 0;
    public int metalBUElementItemState = 0;
    public int thirstBUElementItemState = 0;
    public int septaBUElementItemState = 0;

}
#if UNITY_EDITOR
using UnityEngine;
using System.Collections;
using UnityEditor;

public class MakePlayerData
{
    [MenuItem("Assets/Create/Player Data")]
    public static void createPlayerDataAsset()
    {
        PlayerData asset = ScriptableObject.CreateInstance<PlayerData>();
        AssetDatabase.CreateAsset(asset, "Assets/PlayerData.asset");
        AssetDatabase.SaveAssets();
       
        EditorUtility.FocusProjectWindow();
        Selection.activeObject = asset;
    }
}
#endif

I really hope you can help me.
Thank you!

Cheers,
Arawan

Do you use a custom inspector for your asset or otherwise edit it through scripting?
And if so, are you calling Unity - Scripting API: EditorUtility.SetDirty on them?

1 Like

Yes, I edit the asset through scripting (just changing values).
No I wasn’t calling this method before but I’m doing it now and it looks like working.
But for using this method I have to import the UnityEditor namespace, so I get compiler errors when exporting
(and using the #if UNITY_EDITOR directive doesn’t make sense because then it will only work in the UnityEditor).

Is it possible to call something like EditorUtility.SetDirty(object) without using UnityEditor?
Am I in general on the wrong track or is it legitimate to edit assets at runtime through scripts?

Maybe you’re looking for something like this: Unity - Scripting API: AssetDatabase

But, I think there’s something fundamentally wrong with your design if you’re modifying asset files. Usually you just read from them. What is it you’re actually trying to do?

I’m trying to save my game by creating a class which contains all values I want to store and it derives from ScriptableObject because “This is most useful for assets which are only meant to store data.” (see ScriptReference).
Well, I thought this is one right way of fully controlled saving a game? So I created an asset as described above…
It’s good to hear that assets aren’t meant to modify, normally.
But out of this tutorial I got the idea of storing the game-state as an asset. If we want to load data from a ScriptableObject then we also have to “fill” it with information but how is this done when we shouldn’t modify the variables in the asset?

I’m afraid this approach to saving games won’t work, unless you plan on always playing it in the editor, as you discovered. Assets can’t be saved outside of the editor.
Viable alternatives are storing your values in PlayerPrefs, which should work on any platform.
For larger chunks of data that needs to be saved localy you will probably need to write your own file to disk.
You could also communicate with an online database.

Ok, good to know. Learned something more about assets :roll_eyes:
Thank you all for your kind replies and speedy assistance!
Cheers,
Arawan