Scriptable Object state architecture without a static game state, how to reset the state to default?

Hello,

I’ve been reading/watching about using ScriptableObjects to manage shared state and events (for example this page on game architecture and this unite talk)

One thing I’m still not sure about is how to store the runtime game state, and how to reset it between runs. In my understanding, scriptable objects get persisted in between game runs, which means if I test my game and populate the game state with runtime stuff, it would stay there (and get saved) instead of going back to the default state.

This is undesirable, because let’s say you have a game state with players and their inventory, you wouldn’t really want the default state to change every time you play.

One solution to that is to have a static game state, which is not stored as an asset but generated at runtime, and uses other assets to populate its data. By doing this, the state isn’t saved anywhere so you can ensure a clean new state on every run. I like this way of doing it except it has a few problems:

  • It’s basically a singleton and partly breaks the point of using ScriptableObjects
  • Because said state doesn’t exist in the editor, it can’t have assets plugged to it easily except by loading them at runtime in code.
  • Hooking Scriptable Object Game Events to it becomes a pain because said event assets can’t be referenced in the editor…

So I’m wondering if anyone has suggestions for a different approach, or examples of how they’ve handled the problem of having runtime scriptable objects and needing to go back to the “default” state on game start?

You should ideally treat ScriptableObjects as read-only from a runtime standpoint, slotting them into something else that maintains state.

That said you can have state within them that is not serialized AND resets each time you run in the editor, and also resets each time you start the app. You just mark those variables as [System.NonSerialized].

CAUTION: there is no universal way to reset those states in all Assets when you want to start a fresh game, for example, or reload a game.

I use this decorator in my datasacks package which uses ScriptableObjects for UI interactions and general inter-script communications.

Datasacks is presently hosted at these locations:

https://bitbucket.org/kurtdekker/datasacks

You can see the decoration used on a handful of variables throughout the core classes.

This is true only in the Unity Editor. It is not true in builds.

I have got something like this.
GameRoot.Instance singleton.

That has
object Blackboard.Get()
void Blackboard.Set(object obj)
kind of funcitionality.

I reset this singleton (GameRoot) every time I close the scene, effectively cleaning every data I have put in there.

My ScriptableObjects just call
GameRoot.Instance.Blackboard.Set(object obj)
GameRoot.Instance.Blackboard.Get(object obj)
So I can grab/set current scene data.