Scriptable Object Architecture overview - A Unity architecture for the whole team

Whilst Unity itself is written with a component system architecture in mind, I’ve found it pretty uncommon for most developers to actually utilize any formal architecture or design patterns within their Unity projects. Most find the limitations and overall friction of the engine to be non conducive with most common game development patterns. Usually every pattern I’ve seen attempted in Unity has ran into major roadblocks.

  • I’ve seen monolithic singletons that are fast and simple to make and easy enough to understand. These run into scale and modularity issues as to debug something small you often need more then half the scene and that also goes for attempting to port some feature out of a monolithic structure.

  • I’ve seen Model View Controller patterns that help to split up functions and add some modularity but often become pointless in their splits and I’ve never seen anyone actually use the ability to swap out components. This also creates a lot more up front work for each feature that often feels repetitive.

  • I’ve also seen some Dependency Injection attempted within unity which while it offered modularity and scale solutions it was entirely code based and could not be used by non programmers on the team. It also made debug tracing much harder to follow and regression bugs were really common. This is not to mention it created more up front work for each feature.

Scriptable Object Architecture on the other hand has become a favourite of mine, originating from a 2017 unite talk by Ryan Hipple of Schell Games. The solution offers scalability molecularity and somewhat most importantly it’s much easier to use. To put it simply it is a Inversion of Control pattern that fits Unity much better by utilizing the inspector as a binder whilst also supporting ignoring the binding where it is more convenient and pretending the whole architecture doesn’t exist. Honestly the talk does a much better job of explaining the overall concept but unfortunately SOA really can’t hit it’s stride without some more work from the basic repo supporting the talk. Ryan mentions that the actual implementation they use can’t be shared and can only share the basics which falls short of being truly useful.

Reference structure of SOA.



Getting Started

To kick start an SOA based project I’ve found Atoms I pretty good open source implementation of what SOA should be. It offers some type generation simple to use or ignore reference types and a pretty neat “instancer” system which removes one of the down sides of SOA which is managing and overall abundance of variables living in the project with no clear organization method.

My Design

Compared to the original design of SOA I’ve put more emphasis on Editable and renamed it to usability. I really think one of the biggest strengths of the system is enabling better practices across an entire team regardless of skill level. I’ve also added event driven as optional focus as it can fit Unity a little better and enable more performant code when used correctly.

Original design goals.


I’m going to outline some key differences and additions to SOA that my design and implementations tend to use and which in my opinion really elevate the architecture to new heights.

  • All variables should be fully event driven and the events should be simple externally, i.e. 1 on changed event for the reference, but still listen to inspector and changes regardless of selected type of reference internally. This is also fully ignorable for less skilled developers whilst making refactoring easy later.

  • Steal the instancer system from atoms whilst also introducing binding to other instancers. This supports a Actor pattern that I’m also fond of by allowing prefabs to have 1 instancer reference that is referenced within the prefab whilst binding it per instance to other values.

  • Reference read and write operators. These apply simple operations defined in inspector to read and write operations to the reference. i.e. you can read operate “remap” to take a number value from the range of 0-100 to 0-1 where 50 would be read as 0.5 without editing the actually value. using a write value however takes effect when you write to a value and does effect the actual value for others.

  • Readers and writers are then used as simple components that can use Unity’s event system to “stuff” values with no code and since they are already event driven they become more performant that any repetitive polling script.

  • Also from Atoms we use the idea of having the inspector able to create and populate references on the spot to speed up development time.

  • Events and variables need some debug/tracing tools. Variables can keep logs of past values and read/writes and be accessible in an editor window whilst events can track potential listeners, active listeners and past raisers.

Coming Soon

I’m currently working on a open source implementation of my own to give a starting point for SOA. Sign up too be notified or watch my Github

Previous
Previous

Protem Pieces - Protem Overview

Next
Next

Pass-through AR with Index Controllers