Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct here to familiarize yourself with the rules and how to post constructively.

  2. Unity 2022.1 is now available as the latest Tech release.
    Dismiss Notice

Using scriptable objects for data design, inheritance vs interfaces

Discussion in 'Scripting' started by AhrenM, Dec 11, 2017.

  1. AhrenM

    AhrenM

    Joined:
    Aug 30, 2014
    Posts:
    73
    Hi all,

    There seems to be a bit of a buzz around right now for using scriptable objects for data driven design. It seems like the way we should be working so I thought I'd give it crack. It took me 20 minutes of writing some test scaffolding code to seemingly hit a wall.

    My approach was create a type system that was back ended to scriptable objects. starting with primitive types like an int or a float for example.

    Thing got problematic when I tried to impart my data types with any sort of shared functionality. My first test was a simple observer pattern; the data class notifies subscribed observers (a monobehaviour, cause this is a game engine) when it's base value changes. Pretty handy stuff for a data class to provide irrespective of underling vale.

    Initially I tried abstract base class and inheritance trees. This introduced me to the exciting world of writing custom property drawers for serialised objects and the less said on that the better. Generally property drawers and even custom inspectors don't seem to be a good fit for sub-classed/polymorphic assets.

    To draw on my observer pattern I was going to have to either build an observer script for each data type or a monolithic observer that tried to accommodate all types. Both of which are un-necessary as the observer doesn't care what that value/type is, it's only passing on the message that something has changed.

    Fearing a lot of reflection code in my future, I ported the test code to use an interface to identify shared functionality. This died an even quicker death as Editor support for interfaces is less than inheritance.

    I really am keen to explore data driven design, back-ended to scriptable objects as an architectural pattern, but keep smacking my head into frustrating coding requirements.

    Has anyone got any good ides on building primitive data types with scriptable objects? Has anyone had good success building Editor UI based systems that leveraged inheritance or interfaces on the underlying assets. Are there some good patterns or forum posts that my googling didn't turn up :-(

    Should I just take a deep breath and get better at using reflection?

    I throw it over to the crowd.

    Ahren M
     
  2. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    5,807
    It sounds like you're over-engineering a bit? In particular, where are you running into the need for drawing custom inspectors for subclasses in all of this?


    I find that using ScriptableObjects to contain the data for all the numeric and relational data of our game works very well. But closing at about 500 classes (not including third party plugins), there hasn't really been any need to use a heavy-handed pattern or framework for reacting to changes to those objects. We simply have the SO's that need it expose events, and MonoBehaviours subscribing to those events.

    As an example, we've got GUI icons floating over character's heads, which show changes to those character's stats.
    The stats live in a ScriptableObject instance, and the GUI icons are controlled by a MonoBehaviour. That MonoBehaviour subscribes to an event directly on the ScriptableObject. There's no real indirection anywhere, and I've never run into the need for those SO's to have complex inheritance of any kind. They're mostly just dumb data containers.
     
  3. Ecocide

    Ecocide

    Joined:
    Aug 4, 2011
    Posts:
    292
    Hi AhrenM,

    it seems like this could help you:

    Building primitive data types based on ScriptableObjects is exactly what these guys are doing.
     
unityunity