- Home /
Scriptable Object resets randomly between scenes
I'm using several scriptable objects to store data between scenes. I've noticed recently that some of the data are being reset to what I put in the inspector. I don't have any Awake, OnEnable or OnDisable methods in the scriptable objects.
It feels so random because some of the scriptable objects never reset and behave correctly. Some data persists between two scenes, but when I go to a third scene and come back, that data resets. I do not touch the data in that third scene at all.
The only methods that touch the data are a few setters / getters that I log and they do not get called.
Is there some settings/script that I'm missing to keep my scriptable object data from resetting?
I also noticed that if I have the scriptable object open in the inspector the data persists and works correct; but if I don't have the inspector open the data resets.
Answer by Bunny83 · May 04, 2018 at 11:45 AM
Uhm you know that just changing values of a ScriptableObject through code does not automatically store / serialize those changes? The inspector uses the SerializedObject and SerializedProperty classes to edit the data of a ScriptableObject (or any serialized object for that matter).
When you use your mutating methods like "AddPoints", "ResetPoints", "AddBits", ... you just change the value of the instance in memory but the data is not serialized. Serialization only happens in the editor and only when you tell the editor to serialize the data. It's not clear how and where you use those methods so it's difficult to suggest the best approach.
Though if you actually work with a ScriptableObject that is stored in the project as asset, you could change your mutators to something like this:
void ForceSerialization()
{
#if UNITY_EDITOR
UnityEditor.EditorUtility.SetDirty(this);
#endif
}
public void AddPoints(int value)
{
points += value;
pointsChange.Invoke(points);
ForceSerialization();
}
Though it's generally recommended to seperate editor code and editor functionality from runtime code.
Well i think he actually does want to change the object at runtime in the editor. At least that's what i got from reading this question. Especially the last sentences. Though since it's not clear how he actually "edits" his object we can only speculate. According to his last sentence he doesn't change the object through the inspector. In the comment below mafima's answer he mentions:
Then I run and decrement it to 0 in game
Oh man, thank you so much. I did not realize that scriptableobjects only serialize in the editor. I've been watching a ton of videos on how to use scriptableobjects, and I don't remember hearing that at all.
I thought I could just use them as data containers that persist between scenes.
Answer by misher · Sep 15, 2018 at 05:32 PM
I understand perfectly what did you want to achieve. You wanted to use scriptable objects assets as mutable data containers synchronized in all scenes during runtime(and in the build of course). The problem with "resets" is the following: when a scene is loading, serialized references to assets in this scene will cause instantiating of these assets as new runtime objects, and scriptable object assets are not an exception, therefore, if you have mutated data in the instantiated Asset A
in scene 1, in scene 2 you often will have another instance of Asset A
with all state "resetted" because its object was created from serialized "blueprint" of Asset A
.
And I said "often" for a purpose. I have tested assets behaviour when scene are loaded in editor and in builed app. It turns out, you CAN actually have the same asset (at least scriptable object) instance in different scenes. This is not happening randomly of course. If you have e reference to the Asset A
in scene 1 and you are loading scene 2 where you also have a reference to the same Asset A
, for some mysterious reason your asset instance "pass through" and in scene 2 you will have the same mutaded object. However, if you load some another scene without any reference to the Asset A
, the instance of this asset is "disabled" and when you load again any scene with a reference to the Asset A
, the new instance is created (you can see "awake" and "enable" callbacks being called). So, in order to have your mutated instance of an asset (scriptable object asset) to be the same in all the scenes, you should provide a reference to that asset in every single scene. And this may be easily achieved by creating persistent (DoNotDestroyOnLoad) gameobject in the first scene and make it reference all assets for which you want preserved instances across all scenes.
Now, I really have no idea why this all behaves like this, and I wanted someone to explain this, and the most importantly confirm if it is a correct thing or maybe a bug? Can we actually use this "feature" in production safely? Personally I really like it, because I can make use of scriptable objects in place of singletons without any need for a static references, using Unity's "dependency injection" via inspector.
I'm in the same situation as you: loving ScriptableObjects for game state management but worried about the lack of documentation concerning persistence between scenes. But I found something interesting from Ryan Hipple's blog. Basically, you can set the ScriptableObject's hideFlag to prevent it from unloading through scenes where it's not being referenced, like so:
public class Foobar : ScriptableObject
{
...
private void OnEnable()
{
hideFlags = HideFlags.DontUnloadUnusedAsset;
}
...
}
Such a ScriptableObject will retain its state from its loading throughout the execution. This is giving me more and more the impression that this is indeed intended behaviour.
I feel like your comment should really be an answer, it was exactly what I was looking for~
THAN$$anonymous$$ YOU @lampyridae ! I had similar problem and this absolutely saved me from pulling my hair out!
Answer by mafima · May 03, 2018 at 07:22 PM
"random" does not exist in coding. so do troubleshooting. - does the same thing happens when u create another scriptable object? - if not find what script is modifying the scriptable obj. - if yes there is logic linked to your obj
we could help u more if you give us the code of the relevant scripts. via pastebin.com i hope that helped u
The reset happens to three of my scriptable objects. Here is the most simple one: https://pastebin.com/7$$anonymous$$UHGCna
For example I would set the bits field to 400 via inspector. Then I run and decrement it to 0 in game. When I leave the scene and come back, it resets to 400.
What's stranger is that if I have the PlayerData open in the inspector, it performs as normal and the bits field doesn't get reset back to 400.
I don't know how I can debug this since I can't put break points in the code that's resetting the value. I can't see anything that could trigger the reset.
Answer by Caliber · May 04, 2018 at 08:30 AM
I had something similar happen (also seemed random, when switching scenes).
My issue was that I had mutiple classes in the same file. ScriptableObjects should be in separate files, and the filename must be the same as the name of the class. Could that be the case here?
Your answer
Follow this Question
Related Questions
Why did the values i had set reset? 2 Answers
Loop through a List to check whether a bool is true within a ScriptableObject 1 Answer
Why is play mode reverting my scriptableobject to a previous serialized state? 2 Answers
OnInteractivePreviewGUI multiple selection. Works but spams errors. 0 Answers
Do i need to create a "current value" for those private variables? 0 Answers