Hello everyone. This is my first thread, I hope this is correct forum.
I have question about Scriptable Object Architecture. If you don’t know what SOA is, i strongly recommend you watch this talk. It’s really inspiring.
Lets say i have ‘health’ float variable. In this architecture, i need to reference this health data to scripts that will use it.
Lets also say i have a method that should be called only when this health data is changed. I can easily check if health data is changed on that script’s Update method. But I’m trying to avoid Update method as possible for better performance.
Before i know about SOA, I used to trigger methods when this float data is being set. But is it good approach for this architecture? Should data be used only to get data or is it okey to use it for triggering? Or checking if health data is changed on Update method is not that bad for performance?
Or is there any other way to solve this problem using this architecture?
If you’re not familiar with delegates, time for some studying!
Word of warning though, don’t go overboard with tons of individual value scriptable objects. Best to take the video as small example of what you can do with scriptable objects, and build upon that.
I find scriptable objects work well as containers of various data fit for purpose, rather than singular values.
IMO, this architecture works fine for a small game and a small team but drops off a cliff as soon as you use it at scale or for anything involving a ton of dynamic systems (so… most games)
Scriptable Objects are very good as editor-friendly configs for tweakable game data (like settings of a character controller, a container for SFX data or stats of a weapon). Anything extra (like what ryan gives examples for in that famous talk) will bite your project as it grows.
One I can think of is that there’s no built in way to determine how many objects are referencing a particular SO. So when your event systems are this web of visually disconnected objects, it becomes quite hard to know what is doing what and where.
Kinda thing where some more robust sub-logic systems probably work better in larger projects, such as a high-level node editor to handle common gameplay stuff.
Aren’t scriptable objects another Unity invention for things that have always been done some other way (so I’ve stayed away from them) - maybe they are great, but maybe you should just store data in any other form (xml, csv, JSON, text, WAD!) and load it into a static/singleton/etc class at runtime.
Use delegates for data change events.
If you can do it in standard C# without Unity-specifics - do it!
Well, none of those you can just drop into a field in the inspector. The fact Scriptable objects are UnityEngine.Object’s is what makes them so versatile, that they’re fully supported and serialisable by the inspector.
Yes it is nice from an editor point of view, true.
But if you want designers, testers and other non-Unity users changing those values, do you have a problem?
This is somewhat similar to Qt’s signal/slot approach.
I’m not sure if it is WORTH it, however. Scriptable objects were made for simple inspector support, and inspector works on fields, not properties. So to support your tracked property, you’d need to write a custom inspector.
Btw, there are a gazillion implementations of the ScriptableObject Architecture on github alone.
One of the most advanced is this one:
Also very popular:
And a couple more:
Just because in case you don’t feel like going into wheel invention mode.
At a minimum there’s a ton of nice little solutions for just about everything around this architecture.
When it comes to complexity: I have had SOA in just one large project (team of 4 working on it for 3+ years) and there it was mainly used to take a lot of grunt work and potential points of failure out of the UI. We had many different modes that affected UI (can’t do this in that mode, limit this slider to other values based on some other setting) and different UI modes as well where the same functionality was accessible via drop-down menus, world-space UI (hotspots), VR specific UI and then VR + LeapMotion hand controlling GUI.
Let’s just say without SOA it would have caused TREMENDEOUS headaches, and in fact it did until we added SOA just about one year into the project. Until then, it was common for UI to break, based on modes or changes to business logic, which aggravated the client (are you even testing? ).
I would hesitate using SOA for anything BUT decoupling the UI or potentially some other kind of “external source” like synchronization with a Web or DB API (ideal for caching and using local value store for testing). I wouldn’t want it in game logic, unless we’d be dealing with a plethora of (configurable) variables.
I think the one used in Unity Open Project 1 is a bit different than what Ryan Hipple presented, since the event channels and the connected scripts in UOP 1 are still trackable in Visual Studio IDE?
As one of UOP 1 developers, do you still recommend the ScriptableObject event channel architecture for a sizeable game project? Or better stick with singleton or Dependency Injection?
I’m also worried that those patterns are no longer useable for Unity DOTS in the future.
My personal approach is to ask the question: Is this data needed or defined in the editor outside of playmode?
If yes, consider SOs (consider does not mean “always use”).
If no, then use game objects.
The current health variable is clearly only meaningful in playmode, so not sure why to consider SOs.
Yeah singletons, static variables and sometimes prefabs were the solutions before but since SOs, they have become unncessary workarounds with inferior usability unless you had some custom or 3rd party tooling for this.
From what I remember of the talk the primary purpose of Ryan Hipple’s approach is to tie systems together not to be a way for the people you listed to change the properties of the systems. That said if you wanted to do that you could just have the SOs get their default values from external files.
Thank you all for answers. It’s great to read different opinions.
Thats the anwser that i’m looking for, thanks. Time for some studying!
Hmm. Actually I work on a small games (hypercasual/casual mobile games) with a small team. For now I’ll stick with this archutecture. Thank you so much for your answer.
@CodeSmile I’ll check these implementations and also thanks for sharing your experience.
@DragonCoder I really like your approach, it’s good and simple.
Yes, these are just Unity’s version of storing data that isn’t a part of a scene. However, I’d argue that they’re great precisely because they save you from needing to do that other stuff in most cases.
Important to point out that he also very clearly talks about how its good for opening up things for designers not necessarily actually shippable systems in a released game. I think ryan intended this to be a way to give designers a tool to express their designs, with programmers “cleaning” it up and making it all “work” later on.
I cant imagine ever using this sort of architecture in anything shippable beyond say a game jam sized game.
I just finished a very UI heavy project and it was not pretty! I would love to see an example of how a SO could be used to simplify exactly what you are talking about.
What I did was a nightmare of hooking up buttons to suit the mode. For example, a button to show a screenshot gallery would open a gallery/grid panel of thumbnails (same button disabled the main UI), but if there were no thumbnails, I need a different tutorial/information screen to open. The close buttons on both closed their own panel and ‘enabled’ the main UI again.
That worked fine for one, simple UI but then the client needed many more ‘modes’ and it’s a delicate mess of hooking up this to that, etc. Does Unity have a single authoritative example for how to set up UI’s correctly that will scale?
I feel like the UI Toolkit will ultimately do this best, so when/if that tutorial is ever writting hopefully it will use UI Toolkit. Of course, I had to use animated UI’s and so couldn’t use UI Toolkit. This is why having 3 built-in UI systems is a PITA, just pick one already!