If you are new to ScriptableObjects and want to understand them a bit better first, there's a link in the description to another video on the basics. Then you can rewatch this one with more context. They're a very powerful tool (and deceivingly simple to use!) so we advice getting familiar with them 👍🏻 Do you already use them in creative ways? How?
I wanna put out a big fat warning for using the ScriptableObject architecture to get rid of dependencies! I implemented it with the identical named asset from the store and after watching Ryan Hipple's talk. What sounds like a gift from heaven first, can end in your biggest nightmare very quickly. That is: using ScriptableObjects (SO) completely removes any links. You are not able to see, which class uses or doesn't use this SO "channel". I had like 30 different SO implementations in my project, from input, to all kind of in-game events, then this nightmare became apparent. I could not follow up anymore on who or what actually listened or used those SOs, didn't know what I can safely delete ("maybe some GameObject still uses this SO?" was a common question). It became such a headache at an relatively early stage that I quickly backed off and removed this pattern completely out of my project! Instead, I'm using classical dependency injection - this way, I can see exactly in my IDE (Visual Studio) which class is using what function. And I'm using additive scene loading, to load my game scenes on top, while I have a manager scene from the beginning running at all times (eliminating need of Singleton Pattern). This Manager scene (with Input, SceneManager, Network, Saving/Loading, etc.) populates references to the newly added scene if needed. YES, this makes it harder to just drop in 2-3 components and playtest them quickly without NullRefExceptions, HOWEVER: you can always write your managing code in a way, that it allows all kind of quick playtests with different components, as long as you have your Core Manager scene loaded in the editor and everything else on top. Personally I would never go back to Scriptable Object Archticture, since I learned how to use Additive Scene Loading and inject dependencies over multiple scenes. However I can see where SO Architecture works fine on very small sized projects, like a pin ball game, or VERY simple mobile action game, etc. For anything more complex, anything like an RPG - don't use it for code / logic, only use SO for things like items, buffs, dialogue, ...
@@aldigangster123 Very good point indeed. I also started implementing my SO system after Ryan's talk, and I had to pick up a reference viewer plugin just for that reason. I did however change the idea a bit, where the events are built into the variables themselves, and scripts can subscribe only to certain variable's changes. That way it's not like everything goes through the same channel.
@@aldigangster123 Completely agree. I said the same myself in a much longer reply :) This approach is brilliant on paper, and great for rapid prototyping on a small-ish scale but it falls apart from combinatorial explosion at any meaningful scale - especially as the team size involved increases...
This is actually just a representation of the Observer pattern with pub sub functionality. Really inspiring, I come from a Fullstack Software background and this is really what I was looking for. Perfectly encapsulating the data from the business logic and building a modular way from then to interact without forcing a hard reference. Really good content ❤
Thank you Unity for making a tutorial on proper code architecture. There are so many tutorials out there that teach us beginners anti-patterns, we need you guys to step in and show us how to build our games properly like this. I've watched this video with my Evernote and took notes along the way. I am going to download this open project and study it now. This is exactly what we needed. Also, I love this short devlog/tutorial video format. I can't watch very long videos, don't have time for it. This is more up my alley so maybe do both kinds of formats, long and short ones. And more on proper game architecture please. It's much needed and appreciated!!! 💖💖💖
@@ciankiwi7753 In some ways you actually want to do tasks in a vacuum - that enforced modularity. But I think I get what you're trying to say. Overall though, most tutorials really are very bad, I'm glad we have some proper architecture advice.
This video (particularly the section on input channels) was unbelievably useful for my project. I really struggled to scale my project due to the extreme coupling of different GameObjects via UnityEvents. Whenever this coupling occurred, the prefabs need to be locked together into a super prefab. This is also problematic since I'm making a VR cockpit with both virtual controls and gamepad or touch controller controls. After I watched this video, I spent several hours refactoring my entire codebase to make use of Scriptable Objects. Now every VR control goes into an InputChannel SO, which can have a spaceship avatar (or even enemies!) listen in on the controls. It now becomes even trivial to say, rewire the controls of the cockpit to remotely pilot something else. It's really quite an amazing pattern to learn!
Hey, really appreciate the video on architecture. I'm over here using Godot, but I find a lot of these principles are universal. It's unfortunate that the C# community in Godot isn't as developed and tends to be more hobbyist-level. Would love to see more advanced content like this. Cheers!
Godot as a whole is at a hobbyist level. As Clay John, the Godot rendering team leader said during his GodotCon2023 talk "Right now if you are making a small game it's extremely easy, and if you are making a huge game it's extremely hard." He also stated that's Godot's top priority is ease of use above all else. Godot is software aimed at hobbyists, it's not trying to compete with Unity and such. If you are waiting for the Godot c# community to reach higher levels you might be waiting a while because it's simply not the goal right now.
You say undeniably, but Unreal has a full fledged learning platform similar to that of a college, plus other resources. I think we should just be happy there's two engines with loads of resources at our disposal instead of devolving into tribalism.
@@Helthurian no i used unreal for 2 year , and making 2d games there is no parallax camera, like none. Unreal is great for 3d but you have to do it with blueprints that is not so flexible or vast as unity c#. In unreal if i want to script itS c++ that is absolutely hard language to learn. Plus unity is getting ECS from which its possible to play games like GTA V and other AAA titles games on your mobile phone
I have noticed that in your official tutorial you often do "separator objects": "--------------LIGHTING----------------", and such. ...funny that you haven't thought of the feature that I'm about to suggest now: how about when one gives object a name starting with two dashes "--", it gets converted to and displayed as, proper separator? =D
So basically that's quite a good way to keep the architecture of the game simple and extensible. At work we were using this solution for our project, until we had to use addressables system, which totally doesn't work with what is shown in the video. ScriptableObjects loaded via addressables are totally different instances than the ones that are put directly into the scenes or prefabs. That fact makes this solution unfortunatelly totally unusable, because instead of putting Channels into GameObjects and Scenes directly, you need to load them from addressables each time, or pass them from top to bottom - what this solution is trying to resolve. Is Unity going to do something about it, or suggest any working solutions?
I've visited SO event systems a few times and I don't understand the massive hype that surrounded it about a year ago. A static class in your game is a much more manageable way to dispatch events to whoever needs to know across scenes. Using SOs solves nothing over this and just adds more files to manage. As data containers, SO's are wonderful though.
An easy way to solve that problem is to put the scene and ScriptableObject in Addressable. You cannot refer to Addressable SO from the local scene, but you can refer to Addressable SO from Addressable Scene.
@@yamamuratatsuhiko4762 The scenes were loaded from Addressables, but the behaviour was still wrong - I would have to check if what you are saying is actually right, but it makes sense.
@@Ziplock9000 Don't get me wrong - I'm far from saying that SO systems are the best possible architecture. It is handy especially in small and middle projects, because in larger ones when you put a reference to SO's in every single prefab it might me unmanageable later on. I still much more prefer to use some kind of Dependency Injection, and passing the right systems to the places where they are needed - and that's the solution that I've implemented when when I met the problem with the Scriptable Objects architecture.
@@Ziplock9000 Same, I'm grateful to the SO event architecture hype because it made me understand the usefulness of events as a concept, but once I learned about static events I was like... this is clearly better than SO events... I suppose they still have usefulness for letting designers create more functionality without code, but I agree that they seem to be most useful as data containers.
Ignoring the use of Events/Actions for a moment as they are not exclusive to SOs anyway; Essentially you're using SOs instead of a static class that can span across scenes with the added benefit of it being a monobehavior. SOs don't solve the referencing problems you seem to imply they do at the start of the video, they just make them hard references instead of loose ones via a string. This method also adds another layer between your dispatcher and your receiver, so more objects to juggle and more complications. I still don't get why they add value with a message system above what I've mentioned. However, as data containers able to have inheritance and viewable in the inspector they are wonderful.
This video is HUGE! For too long i was looking for a serious large project made by people who know what their are doing so i could learn pattern and stuff, and the gods have listened!
adding scenes additivelly is the same as adding a singleton to a gameobject and set it to dont destroy on load. Dependency between scenes are still being created in both cases..
Whooo that's super powerful, abstracting out the input to allow anything to listen to it. That's amazing, the subscribers don't need to know how it works/where the input vector is coming from, just that there was a movement. Nice.
Great to have more architecture videos! But I'm not sure why SOs do that you can't do with a singleton. Maybe I looked through to fast but isn't it your design pattern that makes the architecture decoupled and not necessarily placing the event handlers in an SO?
There isn't much that SOs can do IN-GAME that prefabs can't do. SOs nowadays are more for re-usable data and editor assets, since they don't support Component based architecture like MonoBehaviour does.
@@CiroContinisioUnity so it's like you are using SOs kind of lika a unity dependency injection? Instead of having a DI container that you can configure to use for example different managers if you are testing or doing something else you can just switch instance of SO. As long as the fields in the SOs all have the same names. Oh yeah which they of course do cause you are using different instances of the same SO type. So this way the class that calls a handler or manager in the SO have no connection to whatever actually handles the call. It just knows there is a SO that can handle it. I think I get it and I like it.
@@CiroContinisioUnity I'm not quite suggesting that, neither am I disagreeing with using SOs that way. I just prefer using components whenever I can. For example, I'd have the AudioManager which has a field of BaseAudioChannel : MonoBehaviour or something of the like. We can also extend that class (AudioChannelSOConnector : BaseAudioChannel) to have a serialized field of BaseAudioChannelSO : ScriptableObject as a field if we wanted to go the way of SOs. As per the cross scene, in the example above, the main AudioManager class would be a singleton. All in all, I've gotten to use SOs like that in the past and I could not exactly make things as modular as I wanted. Component based architecture has helped me a lot more, since I can achieve whatever I want while also being able to use Component's class advantages.
@@CiroContinisioUnity Ah, I see. My mistake, I didn't realize, despite watching the video, that these SOs are meant for communication purposes only. Hmm, that's quite interesting actually and seems to be a very valid reason for using them. Sorry for that, I'll be watching the videos more carefully from now on!
Great work, started basing everything on scriptable objects, events, data, whole saving system. Thanks for the series. Editor scripts are really useful. Been using Singleton and hard references, but the project gets impossible to scale. Focusing on actual game architecture, flow, best practices but on macro level like this would be awesome.
Unity is so engaging. Like I love Unreal's realism, but not only am I proud of Unity for getting there, but Unity makes 2D and stylized everything so much easier for games. Keep these series up! It's so intuitive using Unity I was surprised I took so long getting started :)
I am writing a game which uses the scriptable object event relay and it has made a *huge* difference to the ease of understanding the code as well as the ability to minimise dependencies. I have always liked events, but as projects have got more complex the events can turn into spaghetti. Using the single scriptable object method instead has totally solved that complexity problem. I think of it as having a central event switchboard rather than individual components wired together. Thanks very much for this.
5:40 I feel like I do somewhat the same thing using a simple static class, not inheriting from MonoBehaviour. Everything in the project can access input through that static class, so I don't see the specificity of ScriptableObject here?
you're using a singleton setup then, which is what they talked about at the beginning. There's plenty of info on singleton vs scriptable objects if you do some googling for more in depth info on the pros/cons of each. I don't think you should expect scriptable objects to suddenly allow you to do something new that you couldn't do with singleton though, they're just a different way of organising things and help make things more modular and flexible
@@r6scrubs126 I think I heard about google before. I ask here to have the chance and the pleasure to interact with humans :) To be more specific with my confusion: the video showcases MonoBehaviour singletons, which have to be incorporated in each Scene or else scripts that need them won't work. Which is not the case with classic singletons that I use freely around. So I don't think the argument "it's scene dependent" used against singleton and in favor of SO, is valid in my situation. Unless I miss something.
@@CiroContinisioUnity That's right, for AudioSource I use MasterAudio so it's a MonoBehaviour singleton indeed. I still have to wrap my head around when to get advantage of the SO tho, I only use them for shared data and never put logic into them like shown in the video. Thanks for the input!
OMG this information challenges my entire custom event system ! I know ScriptableObject for long but just used them for data storage. So I have a few questions : Will you say that this system is efficient for events triggered every frame ? My game is event based and supported by a Singleton (not Mono) EventsManager used to trigger, add listeners, remove listeners, etc. Now I hesitate to upgrade everything to your system. But would that be an upgrade ? This is the question !
depends, if the project is in mid-late production, and its runing fine, i wouldnt change "dont fix it if it int broken" . but if its starting stages, its up to you and your time table.
@@danielr7599 oh no it's far from starting stages, and yes i decided to not change the working system. But I'll check it on a new project just starting soon !
dude if it works, then it works. dont chase any new shining thing. in the video they contradict themselves multiple times. so take what they say with grain of salt.
@@GorasGamesStudio 1. They say if you want test prefab which uses say Audio singleton to play music, then there is dependency. Logically thinking if your object uses some external audio system to play sounds, it already has dependency on it singleton or not. For the very bad example they showed with AudioManagerExample there is multiple ways to test this prefab without any problems, they can create singleton dynamically, they can check if singleton exists in the scene and ignore sound part of the prefab or they can move sound play functionality inside prefab. 2. Every scene in their project have initialization block with pretty much singletons that manage state of the game. 3. Even this small project is mess with i dont know how many different SO everywhere and its impossible to follow whats going on in it. When project is way bigger they many end up with many 1000 of different SO, this is nightmare to manage. 4. Your IDE pretty much useless when everything is setup outside code, you cant follow the code because there are no references . 5. If you ever checked source code of unity game from steam pretty much all of them heavily use singleton pattern without all this overcomplicated engineering.
I am real confused about this. Some are saying that the change in scriptable object is permanent, some are saying it will be reset once the editor is closed.
I really wish they would come up with a Dependency Injection solution instead of making people jump through hoops to provide services. I've been a full stack developer for 10 years, and one of the most baffling things about unity is its inability to conform to industry best practices. Utilizing SOLID principles is a huge pain with unity. Once I picked up Zenject (A IOC framework on the asset store for free). It made a world of difference. SO's are nice to use in certain places, but honestly it still looks like there's way to much dependency on a team of devs knowing which SO to drag into which game object. What's shown here works for a smaller game, but imagine having to track down every little game object to ensure its wired to everything correctly, instead of lets say, injecting an eventListener service in your C# that you can call in code and leave it at that. Seriously, after installing Zenject, I was able to refactor my entire code base, dropping thousands of lines of code, and making it easily maintainable. Its sad that I have to go through a 3rd party asset to do something in C# that at this day and age any mid level c# developer should be doing.
This is just perfect, I wanted to keep a list of spawnable enemies but the problem is that I needed the singleton, but thanks to your tutorial I can now have an internal list without ever having to spawn it
I've been using this architecture for a while now, The main drawback for this, the events lose all references if you change code at run time, which can hurt testing time
@@CiroContinisioUnity no I don't mean when I refactor, just changing code at run time will clear all registered listeners, I have to stop and play the game again
@@CiroContinisioUnity I'd say it's small still, going to medium size, but I usually have some testing scenes that are isolated. Say I'm working on coding a new weapon, changing code at run time can come in handy
Yeah the reference stuff he talks about is just not true. It not only does not solve the referencing issues with singletons or static management classes, but can introduce new problems that you have found. Furthermore, the information needed to re-create those references is lost as they are just NULL rather than just breaking.
I'm sorry guys but this video kinda confirms Unity's philosophy of selling solutions that look easy and shiny without teaching people about the actual cons. They start the video telling about the cons of the singleton pattern saying that you have to recreate the whole game logic in the scene just to test a single functionality.. their solution though is to basically recreate singletons using scriptable objects so the same problem exists only it is hardwired outside the scene so you get the illusion that you've solved the problem while in reality it is still very much there only in a different place. Plus they claim that this solution scales for big projects but they fail completely to mention the deserialisation and loading costs that having hundreds of scriptable objects would bear on a large project leading to impossible loading times and memory costs! They scratch the surface of the maintenance complication of having a large number of small scriptable object assests and only give a hint that you end up with the same spaghetti mess of using singletons (because they are using them as just another flavour of singletons!) This video is terribly misleading and simplistic in my opinion . It would be totally fine if they said : look this is a beginner video and it is fine for small projects, if you want to use this approach for mid sized or larger projects you should thing twice because of this and that performance and memory reason and this and that code architecure and scalability reason... the only added value of this approach to me is that you get a way to have modular singletons.. maybe useful, but at what cost? They fail to mention
No. They actually solved the con they were talking about, it's not an "illusion". If your prefab's scripts are calling into a bunch of singletons, you can't test the prefab in isolation in an empty scene; you have to put all the singletons in the scene as well. Which is not the case with a loosely coupled solution in which all you're doing is raising events. They're not using "another flavor of singletons", they're using classes that communicate between each other via event channels. That's not even remotely similar to singletons. There's no global access, no dependency hiding, and no single instance requirement. Of course there are drawbacks to this solution too (as always): I'd say the main issue with it is that this kind of coupling might be a bit too loose - it adds an extra level of indirection and makes it harder to reason about the program flow, you can't see what functions are being called and in what order just by looking at the code. All you know is you're raising an event. But I don't agree with your objections about "impossible loading times and memory costs" at all. Replacing several monobehaviour singletons with scriptableobjects won't have any noticeable performance implications, of course.
AudioCueEventChannelSO _audioCueEventChannel = default; What does the default mean? Does it choose some sort of default value or in this case SO that you set?
8:20 how is this done with objects loaded in an inactive scene? DontDestroyOnLoads go in their own section. I was curious what exactly is making this happen in this case
Will you say that this system is efficient for events triggered every frame? I had a performance problem once when I tried to send events every frame and then assumed events are not efficient on a per-frame basis.
It's best not to use event systems when something is called very frequently but instead call directly on the method. Personally, I'd consider 60fps too often.
Thank you! In this project are a lot of interesting information to get new skills and approaches. I'm glad to read this code and explore it everyday. Keep in mind, that skill of code reading and understanding is the most required skill as you can recieve!
Got a question here. I started implementing this pattern and found out that, when changing scenes, the references persisted. I have been trying to use UnityEvents, wich flush on scene change, but can't make them work as generic as with Actions/UnityActions. For now, I have an abstract class that contains the flush method and inherits from scriptableobject, then I just use the resources method to find all implementations. But my question is, is there a better way to do this? Again, my problem with UnityEvents is that I have to make an implementation for every combination I need and that's messy.
@@CiroContinisioUnity I didn't want to rely on every subscriber having to control their unsubscription. But that may be the only way since, as you pointed out an I didn't realize, when a subscriber is disabled in the scene, the reference will hold.
@@juampyvarela I would say you need to do that. In my experience it's the correct way of coding. You need to do stuff on start and then you always need to think, what happens, when object is destroyed (or disabled). So you will always have a closed lifecycle. And this way you will always be sure that every time you create/activate, then destroy/deactivate and then again creating/activating a piece of code, it will work the same way every time. Because, for example, you initialize everything OnEnable and reset everything OnDisable
I like using SOs as changeable data containers but as channels, wow I like the approach 🤩 I just need to experiment on it to understand it better for future uses. Thanks for the tutorial 🌟
Nice video, it makes it easier for anyone who wants to jump into the open project mid-way. The open project has proven to be a wealth of useful information on game development, very useful.
There is no problem with the singleton pattern, the problem lies in your misuse of the pattern. Boy this video reminds me of the academics who never wrote a single line of commercial game or application code telling others theory that they do not understand themselves.
@@JackFastGame a SO is literally a singleton. literally all this is is avoiding the S word and replacing it with another S word, except this one binds your code to their tech so it's harder to refactor your game or run away to another engine. totally baffling
Im still trying to understand why create a scriptableobject to read inputs when you can easily add a movement script component to the protagonist. Sorry im dumb.
Strange implementation the Singelton in the Awake(): ... _instance = GetComponent(); ... if (_instance = null) return; These lines change nothing??? :) But also change nothing corresponds to aim of this video - SO is very Helpful
POCO's don't exist as assets that you can plug around using the inspector, so you have to wire everything by code instead of leveraging the Unity Serializer magic
@@Joserbala its very useful at times to lay down data like this but it serves a completely different purpose, that POCO instance cannot be shared throughout several objects /prefabs/scenes at edit time, its like asking "what about using breaks instead of tires in a car", those 2 things are necessary and perfectly valid for their own purpose but cannot do the other's job ! And for that matter, at some point you'll probably end up with POCOs serialized in your SOs ;)
I get the problem with singletons, but what about static classes? Setting up references to scriptable objects for every class & every prefab that has that class (let alone null checking the references for when you edit the code during runtime), it seems incredibly time consuming in the long run.
All content creators making tutorials should learn from this video: pace, snippets, diagrams, increasing complexity. Just perfect, well done Unity guys!
@@aranna5372 : They are completely different tools. While Bolt has a Finite State Machine, like many visual scripting tools, it isn't designed for that first and foremost. They are very different. Look up "NodeCanvas" (Playmaker competitor) and "FlowCanvas" (Bolt competitor). They are both by the same company, can work together, but do very different things.
So, Mixing ScriptableObjects with the Observer pattern is how Unity recommends games should be developed. I wish there was a full tutorial for a complete project for that.
Been using unity for a little bit now as I learned coding and my friend and I use So's quite a bit in our projects and I was curious what the purpose of using them as channels instead of standalone objects is. For instance, your input system is an SO that contains all the interfacing and actions needed for doing its job. Your audio and scene loading systems, however, exist on monobehaviours and and use channels to give and receive information. In our projects we have simply made these systems entirely as SO's and plugged them into whatever needs access to them. As i said, I'm by no means a trained developer and could be missing something simple. I know monobehaviours have access to different things like update and fixedupdate while SO's dont. Is there another reason to use this pattern?
@@CiroContinisioUnity Singleton's purpose is to only and only ensure creation and usage of only one instance of a class as you know. Not provide global access as many people think. So-called "Unity Singleton" allow creation of multiple instances, they just ensure deleting of "new ones" but it's very different from not allowing and making absolutely impossible to create new instances of a class.
Yeah, this incorporated a lot of things I'm unfamiliar with, Events, delegates, additive scenes and I think that's it. SO's themselves are simple enough, they are Data containers without the benefits of Monobehavior. Since they are assets that can use Unity Events then having them take the place in some ways of the Manager type scripts is a thing. So I am going to assume the reason for the additive scene is to further avoid the Singleton for this example. Alright then, thanks for this all.
If you are new to ScriptableObjects and want to understand them a bit better first, there's a link in the description to another video on the basics. Then you can rewatch this one with more context. They're a very powerful tool (and deceivingly simple to use!) so we advice getting familiar with them 👍🏻
Do you already use them in creative ways? How?
Connections the UI! Just like you showed here
I wanna put out a big fat warning for using the ScriptableObject architecture to get rid of dependencies! I implemented it with the identical named asset from the store and after watching Ryan Hipple's talk. What sounds like a gift from heaven first, can end in your biggest nightmare very quickly. That is: using ScriptableObjects (SO) completely removes any links. You are not able to see, which class uses or doesn't use this SO "channel". I had like 30 different SO implementations in my project, from input, to all kind of in-game events, then this nightmare became apparent. I could not follow up anymore on who or what actually listened or used those SOs, didn't know what I can safely delete ("maybe some GameObject still uses this SO?" was a common question). It became such a headache at an relatively early stage that I quickly backed off and removed this pattern completely out of my project! Instead, I'm using classical dependency injection - this way, I can see exactly in my IDE (Visual Studio) which class is using what function. And I'm using additive scene loading, to load my game scenes on top, while I have a manager scene from the beginning running at all times (eliminating need of Singleton Pattern). This Manager scene (with Input, SceneManager, Network, Saving/Loading, etc.) populates references to the newly added scene if needed. YES, this makes it harder to just drop in 2-3 components and playtest them quickly without NullRefExceptions, HOWEVER: you can always write your managing code in a way, that it allows all kind of quick playtests with different components, as long as you have your Core Manager scene loaded in the editor and everything else on top.
Personally I would never go back to Scriptable Object Archticture, since I learned how to use Additive Scene Loading and inject dependencies over multiple scenes. However I can see where SO Architecture works fine on very small sized projects, like a pin ball game, or VERY simple mobile action game, etc. For anything more complex, anything like an RPG - don't use it for code / logic, only use SO for things like items, buffs, dialogue, ...
@@aldigangster123 you can always use "Find reference in scene" but I see your point. I have not had the issues you have had though personally
@@aldigangster123 Very good point indeed. I also started implementing my SO system after Ryan's talk, and I had to pick up a reference viewer plugin just for that reason. I did however change the idea a bit, where the events are built into the variables themselves, and scripts can subscribe only to certain variable's changes. That way it's not like everything goes through the same channel.
@@aldigangster123 Completely agree. I said the same myself in a much longer reply :) This approach is brilliant on paper, and great for rapid prototyping on a small-ish scale but it falls apart from combinatorial explosion at any meaningful scale - especially as the team size involved increases...
This is actually just a representation of the Observer pattern with pub sub functionality. Really inspiring, I come from a Fullstack Software background and this is really what I was looking for. Perfectly encapsulating the data from the business logic and building a modular way from then to interact without forcing a hard reference. Really good content ❤
Whoever decided to make this tutorial: thank you
Thank you Unity for making a tutorial on proper code architecture. There are so many tutorials out there that teach us beginners anti-patterns, we need you guys to step in and show us how to build our games properly like this. I've watched this video with my Evernote and took notes along the way. I am going to download this open project and study it now. This is exactly what we needed.
Also, I love this short devlog/tutorial video format. I can't watch very long videos, don't have time for it. This is more up my alley so maybe do both kinds of formats, long and short ones. And more on proper game architecture please. It's much needed and appreciated!!! 💖💖💖
THIS ^^^
alot of tutorials will show how to complete the task in a vacuum, but fail to explain how to put it into an actual game.
@@ciankiwi7753 In some ways you actually want to do tasks in a vacuum - that enforced modularity. But I think I get what you're trying to say.
Overall though, most tutorials really are very bad, I'm glad we have some proper architecture advice.
This video (particularly the section on input channels) was unbelievably useful for my project.
I really struggled to scale my project due to the extreme coupling of different GameObjects via UnityEvents. Whenever this coupling occurred, the prefabs need to be locked together into a super prefab. This is also problematic since I'm making a VR cockpit with both virtual controls and gamepad or touch controller controls. After I watched this video, I spent several hours refactoring my entire codebase to make use of Scriptable Objects. Now every VR control goes into an InputChannel SO, which can have a spaceship avatar (or even enemies!) listen in on the controls. It now becomes even trivial to say, rewire the controls of the cockpit to remotely pilot something else. It's really quite an amazing pattern to learn!
One year later and I'd still say this is the most useful Unity educational video!
Unrelated but I love voiceover guy's voice. Instantly recognisable and very calming.
Hey, really appreciate the video on architecture. I'm over here using Godot, but I find a lot of these principles are universal.
It's unfortunate that the C# community in Godot isn't as developed and tends to be more hobbyist-level.
Would love to see more advanced content like this. Cheers!
Godot as a whole is at a hobbyist level. As Clay John, the Godot rendering team leader said during his GodotCon2023 talk "Right now if you are making a small game it's extremely easy, and if you are making a huge game it's extremely hard." He also stated that's Godot's top priority is ease of use above all else. Godot is software aimed at hobbyists, it's not trying to compete with Unity and such. If you are waiting for the Godot c# community to reach higher levels you might be waiting a while because it's simply not the goal right now.
This is where Unity beats Unreal and any other Game Engine undeniably: Education.
You say undeniably, but Unreal has a full fledged learning platform similar to that of a college, plus other resources. I think we should just be happy there's two engines with loads of resources at our disposal instead of devolving into tribalism.
@@Helthurian it’s not tribalism to simply have an opinion on what’s better
@@illsaveus you can't know what is better if never tried something else. How about Godot? Never heard about, huh? Stop being shallow.
@@Helthurian no i used unreal for 2 year , and making 2d games there is no parallax camera, like none. Unreal is great for 3d but you have to do it with blueprints that is not so flexible or vast as unity c#. In unreal if i want to script itS c++ that is absolutely hard language to learn.
Plus unity is getting ECS from which its possible to play games like GTA V and other AAA titles games on your mobile phone
Plus ECS, my mind was blown when they played their demo in iphone
I finally understand how to use SO as event channels, ty
I honestly feel like this 'data asset' pattern is the long-term way forward for Unity, in terms of usability. Praise Ryan!
You still have to invoke and subscribe, so it can never just be data driven.
@@Ziplock9000 Yeah not purely.
This is awesome. You should pay more attention to game architecture. Thanks for this one and good luck on UOP ;)
I think this is exactly what I needed. I kind of started using SOs like this, but I didn't fully grasp what I could do with it. Thank you for this.
I have noticed that in your official tutorial you often do "separator objects": "--------------LIGHTING----------------", and such.
...funny that you haven't thought of the feature that I'm about to suggest now: how about when one gives object a name starting with two dashes "--", it gets converted to and displayed as, proper separator? =D
Better yet, cosmetic-only folders in the hierarchy. Collapse-able without the need of any transform parenting.
Thank you. This is gold.
What's the issue with making the event channels static classes that don't necessarily need to be instantiated?
I love being a game dev.
I started using SO’s in my NetworkBehaviors and things got really messed up! Please make a tutorial with SO’s and Network Patterns.
Im not joking but this is very useful and helped a lot with my workflow.
Great video ❤
Can I ask you to come ant watch my Videos ?
If it posible
So basically that's quite a good way to keep the architecture of the game simple and extensible. At work we were using this solution for our project, until we had to use addressables system, which totally doesn't work with what is shown in the video.
ScriptableObjects loaded via addressables are totally different instances than the ones that are put directly into the scenes or prefabs. That fact makes this solution unfortunatelly totally unusable, because instead of putting Channels into GameObjects and Scenes directly, you need to load them from addressables each time, or pass them from top to bottom - what this solution is trying to resolve.
Is Unity going to do something about it, or suggest any working solutions?
I've visited SO event systems a few times and I don't understand the massive hype that surrounded it about a year ago. A static class in your game is a much more manageable way to dispatch events to whoever needs to know across scenes. Using SOs solves nothing over this and just adds more files to manage. As data containers, SO's are wonderful though.
An easy way to solve that problem is to put the scene and ScriptableObject in Addressable.
You cannot refer to Addressable SO from the local scene, but you can refer to Addressable SO from Addressable Scene.
@@yamamuratatsuhiko4762 The scenes were loaded from Addressables, but the behaviour was still wrong - I would have to check if what you are saying is actually right, but it makes sense.
@@Ziplock9000 Don't get me wrong - I'm far from saying that SO systems are the best possible architecture. It is handy especially in small and middle projects, because in larger ones when you put a reference to SO's in every single prefab it might me unmanageable later on.
I still much more prefer to use some kind of Dependency Injection, and passing the right systems to the places where they are needed - and that's the solution that I've implemented when when I met the problem with the Scriptable Objects architecture.
@@Ziplock9000 Same, I'm grateful to the SO event architecture hype because it made me understand the usefulness of events as a concept, but once I learned about static events I was like... this is clearly better than SO events... I suppose they still have usefulness for letting designers create more functionality without code, but I agree that they seem to be most useful as data containers.
Ignoring the use of Events/Actions for a moment as they are not exclusive to SOs anyway; Essentially you're using SOs instead of a static class that can span across scenes with the added benefit of it being a monobehavior. SOs don't solve the referencing problems you seem to imply they do at the start of the video, they just make them hard references instead of loose ones via a string. This method also adds another layer between your dispatcher and your receiver, so more objects to juggle and more complications. I still don't get why they add value with a message system above what I've mentioned. However, as data containers able to have inheritance and viewable in the inspector they are wonderful.
Thanks. These focussed videos are much more useful than the live development streams (which I find to be a bit waffley).
This video is HUGE! For too long i was looking for a serious large project made by people who know what their are doing so i could learn pattern and stuff, and the gods have listened!
Unity, I love your education and your engine! Thank you a lot folks! You've changed my life!
adding scenes additivelly is the same as adding a singleton to a gameobject and set it to dont destroy on load. Dependency between scenes are still being created in both cases..
Whooo that's super powerful, abstracting out the input to allow anything to listen to it. That's amazing, the subscribers don't need to know how it works/where the input vector is coming from, just that there was a movement. Nice.
Very interesting and useful...
Great to have more architecture videos! But I'm not sure why SOs do that you can't do with a singleton. Maybe I looked through to fast but isn't it your design pattern that makes the architecture decoupled and not necessarily placing the event handlers in an SO?
There isn't much that SOs can do IN-GAME that prefabs can't do. SOs nowadays are more for re-usable data and editor assets, since they don't support Component based architecture like MonoBehaviour does.
@@CiroContinisioUnity so it's like you are using SOs kind of lika a unity dependency injection? Instead of having a DI container that you can configure to use for example different managers if you are testing or doing something else you can just switch instance of SO. As long as the fields in the SOs all have the same names. Oh yeah which they of course do cause you are using different instances of the same SO type. So this way the class that calls a handler or manager in the SO have no connection to whatever actually handles the call. It just knows there is a SO that can handle it.
I think I get it and I like it.
@@CiroContinisioUnity I'm not quite suggesting that, neither am I disagreeing with using SOs that way. I just prefer using components whenever I can. For example, I'd have the AudioManager which has a field of BaseAudioChannel : MonoBehaviour or something of the like. We can also extend that class (AudioChannelSOConnector : BaseAudioChannel) to have a serialized field of BaseAudioChannelSO : ScriptableObject as a field if we wanted to go the way of SOs.
As per the cross scene, in the example above, the main AudioManager class would be a singleton. All in all, I've gotten to use SOs like that in the past and I could not exactly make things as modular as I wanted. Component based architecture has helped me a lot more, since I can achieve whatever I want while also being able to use Component's class advantages.
@@CiroContinisioUnity Ah, I see. My mistake, I didn't realize, despite watching the video, that these SOs are meant for communication purposes only. Hmm, that's quite interesting actually and seems to be a very valid reason for using them. Sorry for that, I'll be watching the videos more carefully from now on!
Great work, started basing everything on scriptable objects, events, data, whole saving system. Thanks for the series. Editor scripts are really useful. Been using Singleton and hard references, but the project gets impossible to scale.
Focusing on actual game architecture, flow, best practices but on macro level like this would be awesome.
Unity is so engaging.
Like I love Unreal's realism, but not only am I proud of Unity for getting there, but Unity makes 2D and stylized everything so much easier for games.
Keep these series up! It's so intuitive using Unity I was surprised I took so long getting started :)
I agree w/ you, one of the reasons Unity is so good is because of its user and beginner-friendly layout.
Nowadays Unity is able to demonstrate similar graphics level as Unreal does.
This is exactly what I need right now "Game Architecture"! Ayo thanks Unity!
I am writing a game which uses the scriptable object event relay and it has made a *huge* difference to the ease of understanding the code as well as the ability to minimise dependencies.
I have always liked events, but as projects have got more complex the events can turn into spaghetti. Using the single scriptable object method instead has totally solved that complexity problem. I think of it as having a central event switchboard rather than individual components wired together. Thanks very much for this.
5:40 I feel like I do somewhat the same thing using a simple static class, not inheriting from MonoBehaviour. Everything in the project can access input through that static class, so I don't see the specificity of ScriptableObject here?
you're using a singleton setup then, which is what they talked about at the beginning. There's plenty of info on singleton vs scriptable objects if you do some googling for more in depth info on the pros/cons of each. I don't think you should expect scriptable objects to suddenly allow you to do something new that you couldn't do with singleton though, they're just a different way of organising things and help make things more modular and flexible
@@r6scrubs126 I think I heard about google before. I ask here to have the chance and the pleasure to interact with humans :) To be more specific with my confusion: the video showcases MonoBehaviour singletons, which have to be incorporated in each Scene or else scripts that need them won't work. Which is not the case with classic singletons that I use freely around. So I don't think the argument "it's scene dependent" used against singleton and in favor of SO, is valid in my situation. Unless I miss something.
@@CiroContinisioUnity That's right, for AudioSource I use MasterAudio so it's a MonoBehaviour singleton indeed. I still have to wrap my head around when to get advantage of the SO tho, I only use them for shared data and never put logic into them like shown in the video. Thanks for the input!
Same here! Love the vid, but a static class works similar for me as an event bus. What would be the advantages of SSO here?
Great great great video, thanks Unity !
OMG this information challenges my entire custom event system ! I know ScriptableObject for long but just used them for data storage. So I have a few questions :
Will you say that this system is efficient for events triggered every frame ?
My game is event based and supported by a Singleton (not Mono) EventsManager used to trigger, add listeners, remove listeners, etc.
Now I hesitate to upgrade everything to your system. But would that be an upgrade ? This is the question !
depends, if the project is in mid-late production, and its runing fine, i wouldnt change "dont fix it if it int broken" . but if its starting stages, its up to you and your time table.
@@danielr7599 oh no it's far from starting stages, and yes i decided to not change the working system. But I'll check it on a new project just starting soon !
dude if it works, then it works. dont chase any new shining thing. in the video they contradict themselves multiple times. so take what they say with grain of salt.
@@lazysnail145 Yes but always looking for a better solution, more efficient. How did they contradict themselves ?
@@GorasGamesStudio 1. They say if you want test prefab which uses say Audio singleton to play music, then there is dependency. Logically thinking if your object uses some external audio system to play sounds, it already has dependency on it singleton or not. For the very bad example they showed with AudioManagerExample there is multiple ways to test this prefab without any problems, they can create singleton dynamically, they can check if singleton exists in the scene and ignore sound part of the prefab or they can move sound play functionality inside prefab.
2. Every scene in their project have initialization block with pretty much singletons that manage state of the game.
3. Even this small project is mess with i dont know how many different SO everywhere and its impossible to follow whats going on in it. When project is way bigger they many end up with many 1000 of different SO, this is nightmare to manage.
4. Your IDE pretty much useless when everything is setup outside code, you cant follow the code because there are no references .
5. If you ever checked source code of unity game from steam pretty much all of them heavily use singleton pattern without all this overcomplicated engineering.
I am real confused about this. Some are saying that the change in scriptable object is permanent, some are saying it will be reset once the editor is closed.
I would like to know more about the sound system. Where can I find more information about such a system? 07:13 - Events for playing audio
I'm watching this a day after I figured exactly the same thing on my own XD
I really wish they would come up with a Dependency Injection solution instead of making people jump through hoops to provide services. I've been a full stack developer for 10 years, and one of the most baffling things about unity is its inability to conform to industry best practices. Utilizing SOLID principles is a huge pain with unity. Once I picked up Zenject (A IOC framework on the asset store for free). It made a world of difference. SO's are nice to use in certain places, but honestly it still looks like there's way to much dependency on a team of devs knowing which SO to drag into which game object. What's shown here works for a smaller game, but imagine having to track down every little game object to ensure its wired to everything correctly, instead of lets say, injecting an eventListener service in your C# that you can call in code and leave it at that.
Seriously, after installing Zenject, I was able to refactor my entire code base, dropping thousands of lines of code, and making it easily maintainable. Its sad that I have to go through a 3rd party asset to do something in C# that at this day and age any mid level c# developer should be doing.
This is why I love Unity, they have great educational tools which invigorate my excitement in game development
This is just perfect, I wanted to keep a list of spawnable enemies but the problem is that I needed the singleton, but thanks to your tutorial I can now have an internal list without ever having to spawn it
I've been using this architecture for a while now,
The main drawback for this, the events lose all references if you change code at run time, which can hurt testing time
@@CiroContinisioUnity no I don't mean when I refactor, just changing code at run time will clear all registered listeners, I have to stop and play the game again
@@CiroContinisioUnity well yeah, it's minor inconvenience, but for testing, sometimes it speed things up
@@CiroContinisioUnity I'd say it's small still, going to medium size, but I usually have some testing scenes that are isolated.
Say I'm working on coding a new weapon, changing code at run time can come in handy
Yeah the reference stuff he talks about is just not true. It not only does not solve the referencing issues with singletons or static management classes, but can introduce new problems that you have found. Furthermore, the information needed to re-create those references is lost as they are just NULL rather than just breaking.
Would this technique be suitable for disseminating data from the network?
The architecture is great for modularity, but what about the memory garbage generated by Unity Events? Why not use ECS instead?
Thank you for your Great Engine
I'm sorry guys but this video kinda confirms Unity's philosophy of selling solutions that look easy and shiny without teaching people about the actual cons.
They start the video telling about the cons of the singleton pattern saying that you have to recreate the whole game logic in the scene just to test a single functionality.. their solution though is to basically recreate singletons using scriptable objects so the same problem exists only it is hardwired outside the scene so you get the illusion that you've solved the problem while in reality it is still very much there only in a different place.
Plus they claim that this solution scales for big projects but they fail completely to mention the deserialisation and loading costs that having hundreds of scriptable objects would bear on a large project leading to impossible loading times and memory costs! They scratch the surface of the maintenance complication of having a large number of small scriptable object assests and only give a hint that you end up with the same spaghetti mess of using singletons (because they are using them as just another flavour of singletons!)
This video is terribly misleading and simplistic in my opinion . It would be totally fine if they said : look this is a beginner video and it is fine for small projects, if you want to use this approach for mid sized or larger projects you should thing twice because of this and that performance and memory reason and this and that code architecure and scalability reason... the only added value of this approach to me is that you get a way to have modular singletons.. maybe useful, but at what cost? They fail to mention
No. They actually solved the con they were talking about, it's not an "illusion". If your prefab's scripts are calling into a bunch of singletons, you can't test the prefab in isolation in an empty scene; you have to put all the singletons in the scene as well. Which is not the case with a loosely coupled solution in which all you're doing is raising events. They're not using "another flavor of singletons", they're using classes that communicate between each other via event channels. That's not even remotely similar to singletons. There's no global access, no dependency hiding, and no single instance requirement. Of course there are drawbacks to this solution too (as always): I'd say the main issue with it is that this kind of coupling might be a bit too loose - it adds an extra level of indirection and makes it harder to reason about the program flow, you can't see what functions are being called and in what order just by looking at the code. All you know is you're raising an event. But I don't agree with your objections about "impossible loading times and memory costs" at all. Replacing several monobehaviour singletons with scriptableobjects won't have any noticeable performance implications, of course.
there are 2 audio listeners in the scene. Please ensure there is always exactly one audio listener in the scene.
AudioCueEventChannelSO _audioCueEventChannel = default;
What does the default mean? Does it choose some sort of default value or in this case SO that you set?
10:30 have this custom inspector done in those next episodes?
8:20 how is this done with objects loaded in an inactive scene? DontDestroyOnLoads go in their own section. I was curious what exactly is making this happen in this case
Will you say that this system is efficient for events triggered every frame?
I had a performance problem once when I tried to send events every frame and then assumed events are not efficient on a per-frame basis.
It's best not to use event systems when something is called very frequently but instead call directly on the method. Personally, I'd consider 60fps too often.
You are doing a great job with this series. Keep it up!
Thank you! In this project are a lot of interesting information to get new skills and approaches. I'm glad to read this code and explore it everyday. Keep in mind, that skill of code reading and understanding is the most required skill as you can recieve!
How did that initialization scene work, How did it stay when other scene was active ?
The initialization scene is unloaded only after the persistentManager scene has been loaded.
Top quality content! A must watch for anyone who wants to make their game in a scalable way .
useful video from unity
The project is really taking form! This series is becoming very interesting to watch and I am also loving to follow the development of the project.
very good 👍
omg, this is exactly what I expect to learn how to make a game! Thank you guys so much! I love this kind of easy-to-learn game architecture!
Got a question here. I started implementing this pattern and found out that, when changing scenes, the references persisted. I have been trying to use UnityEvents, wich flush on scene change, but can't make them work as generic as with Actions/UnityActions. For now, I have an abstract class that contains the flush method and inherits from scriptableobject, then I just use the resources method to find all implementations. But my question is, is there a better way to do this? Again, my problem with UnityEvents is that I have to make an implementation for every combination I need and that's messy.
@@CiroContinisioUnity I didn't want to rely on every subscriber having to control their unsubscription. But that may be the only way since, as you pointed out an I didn't realize, when a subscriber is disabled in the scene, the reference will hold.
@@CiroContinisioUnity And thank you for the answer ❤️
@@juampyvarela I would say you need to do that. In my experience it's the correct way of coding. You need to do stuff on start and then you always need to think, what happens, when object is destroyed (or disabled). So you will always have a closed lifecycle. And this way you will always be sure that every time you create/activate, then destroy/deactivate and then again creating/activating a piece of code, it will work the same way every time. Because, for example, you initialize everything OnEnable and reset everything OnDisable
Excellent
Thanks, guys that's awesome, I've been wondering what architecture I should use.
I like using SOs as changeable data containers but as channels, wow I like the approach 🤩 I just need to experiment on it to understand it better for future uses. Thanks for the tutorial 🌟
Nice video, it makes it easier for anyone who wants to jump into the open project mid-way. The open project has proven to be a wealth of useful information on game development, very useful.
There is no problem with the singleton pattern, the problem lies in your misuse of the pattern. Boy this video reminds me of the academics who never wrote a single line of commercial game or application code telling others theory that they do not understand themselves.
So what's the right approach of using singleton?
@@JackFastGame a SO is literally a singleton. literally all this is is avoiding the S word and replacing it with another S word, except this one binds your code to their tech so it's harder to refactor your game or run away to another engine. totally baffling
@@el_primer_y_el_ultimo_caiman It's not a singleton by any means. Simply because you can create many instances of SO.
This video is nice.
Yes It was nice and Useful
❤️
I always used SO's just as data containers with minimal functionality. Never thought of using it in this way. That's pretty clever.
Thanks for the video. This will be a great help on my journey in Unity
Doe's scriptble objects remember change from scene to scene in build?
Yes
Another abandoned project from Unity. The list just keeps growing.
Im still trying to understand why create a scriptableobject to read inputs when you can easily add a movement script component to the protagonist. Sorry im dumb.
Because the protagonist might not be the only object in the scene that reacts to input.
@@snaileri I see, good point
we need to make spanish localization a thing
Great tutorial. However a better approach would be using a dependency injection system like extenject
NICE
🤯
One of the most useful Unity videos in a lot of time
This was actually very informative! Thanks! I have always wondered how to escape singletons! This is what I was looking for!
Strange implementation the Singelton in the Awake():
...
_instance = GetComponent();
...
if (_instance = null)
return;
These lines change nothing???
:) But also change nothing corresponds to aim of this video - SO is very Helpful
Milk
Oh wait wrong channel
Karlson
I don't get the difference between this and plain C# classes, someone could explain please?
POCO's don't exist as assets that you can plug around using the inspector, so you have to wire everything by code instead of leveraging the Unity Serializer magic
@@GuillaumeKehren oh, I see. And what about putting a POCO as Serializable and inserting in a Monobehaviour? I'm only two months into Unity hehe
@@Joserbala its very useful at times to lay down data like this but it serves a completely different purpose, that POCO instance cannot be shared throughout several objects /prefabs/scenes at edit time, its like asking "what about using breaks instead of tires in a car", those 2 things are necessary and perfectly valid for their own purpose but cannot do the other's job !
And for that matter, at some point you'll probably end up with POCOs serialized in your SOs ;)
@@GuillaumeKehren oh, I see! Thank you so much! :D
I'm coming from a native mobile background and I love this. I want to make a 2d game while implementing similar architecture.
I get the problem with singletons, but what about static classes? Setting up references to scriptable objects for every class & every prefab that has that class (let alone null checking the references for when you edit the code during runtime), it seems incredibly time consuming in the long run.
All content creators making tutorials should learn from this video: pace, snippets, diagrams, increasing complexity. Just perfect, well done Unity guys!
wish i knew about thid ealier
cool.
When did Bolt 2 coming
It isn't. Bolt 2 was canceled and instead they are focus on Bolt 1 =/
Playmaker is far better
@@aranna5372 : What? Playmaker is an FSM... it isn't a visual scripting tool.
@@StefanLopuszanski its True
Buts difrent betwin them ?
@@aranna5372 : They are completely different tools. While Bolt has a Finite State Machine, like many visual scripting tools, it isn't designed for that first and foremost. They are very different. Look up "NodeCanvas" (Playmaker competitor) and "FlowCanvas" (Bolt competitor). They are both by the same company, can work together, but do very different things.
These tutorials are REALLY GREAT Unity! Please keep doing these with advanced topics!
почему вы закрыли проект battle of zombies?😢😭
Is there an existing GTA like open project? I mean I don't want to end up like Cyberpunk 2077 fans complain. bad graphics load, physics, and glitches.
So, Mixing ScriptableObjects with the Observer pattern is how Unity recommends games should be developed. I wish there was a full tutorial for a complete project for that.
Wow this is all too advanced for me. I hope I learn to do this soon! It sounds amazing!!
Been using unity for a little bit now as I learned coding and my friend and I use So's quite a bit in our projects and I was curious what the purpose of using them as channels instead of standalone objects is. For instance, your input system is an SO that contains all the interfacing and actions needed for doing its job. Your audio and scene loading systems, however, exist on monobehaviours and and use channels to give and receive information. In our projects we have simply made these systems entirely as SO's and plugged them into whatever needs access to them. As i said, I'm by no means a trained developer and could be missing something simple. I know monobehaviours have access to different things like update and fixedupdate while SO's dont. Is there another reason to use this pattern?
What's chop-chop?
@@CiroContinisioUnity nice, thanks
pub-sub, nice!
I am 907.001 subscriber 😅
Just use statics.
Pls add Unity for linux chromebook so I can do my game dev
Great initiative, @Unity, but please stop calling those abominations "Singletons" they are just not.
@@CiroContinisioUnity Singleton's purpose is to only and only ensure creation and usage of only one instance of a class as you know. Not provide global access as many people think. So-called "Unity Singleton" allow creation of multiple instances, they just ensure deleting of "new ones" but it's very different from not allowing and making absolutely impossible to create new instances of a class.
Yeah, this incorporated a lot of things I'm unfamiliar with, Events, delegates, additive scenes and I think that's it. SO's themselves are simple enough, they are Data containers without the benefits of Monobehavior.
Since they are assets that can use Unity Events then having them take the place in some ways of the Manager type scripts is a thing.
So I am going to assume the reason for the additive scene is to further avoid the Singleton for this example.
Alright then, thanks for this all.