The Power of Scriptable Objects as Middle-Men

แชร์
ฝัง
  • เผยแพร่เมื่อ 27 ก.ย. 2024

ความคิดเห็น • 249

  • @alfredoheights
    @alfredoheights 2 ปีที่แล้ว +14

    Thank you, this did so much more for me than the Unite Austin talk. I could not ever wrap my mind around what he was saying, but this is just a really well-done demonstration.

    • @samyam
      @samyam  2 ปีที่แล้ว +1

      Thank you! Appreciate the kind words 😁

  • @AliceLoverdrive
    @AliceLoverdrive 2 ปีที่แล้ว +172

    A word of caution: since ScriptableObjects retain values _after_ exiting play mode, this approach may lead to undoing previous work if you ain't careful enough. Otherwise, great tutorial. I'd personally attack the problem in an example from a different angle, but it does illustrate the point fairly well.

    • @danielfazly1350
      @danielfazly1350 2 ปีที่แล้ว +42

      Yep, this is a common problem. Instead of altering the ScriptableObject, your scripts should make a new instance of it and alter that instead.

    • @MattiaBelletti
      @MattiaBelletti 2 ปีที่แล้ว +1

      I'm interested in comparing various solutions for this kind of problems: which architecture would you put in place to solve it?

    • @AliceLoverdrive
      @AliceLoverdrive 2 ปีที่แล้ว +14

      ​@@MattiaBelletti in this particular case, I'd go simple and just mark both player character's GO and UI manager go as DontDestroyOnLoad -- it's highly unlikely that the only data you'd need to retain about the player character is their health, after all.
      Also, I'd just make UI manager to FIndObjectOfType on awake to avoid making PlayerCharacter class being dependent on UI.

    • @CockroachSlidy
      @CockroachSlidy 2 ปีที่แล้ว +11

      @@danielfazly1350 No need for that. Just create properties and assign them from serialized fields in OnEnable in your scriptable objects. This way you can separate runtime data or even fetch it from PlayerPreafs.

    • @callmedeno
      @callmedeno 2 ปีที่แล้ว +1

      @@CockroachSlidy Can you explain that a bit more? So you have a sctiptable object which has default values, then in on on enable you get them from what serialized fields, from where a file?

  • @empty5013
    @empty5013 2 ปีที่แล้ว +21

    singletons are actually used in games more than most other programming fields because the usual downsides of singleton (global state) are not as bad in video games since you know your code will be run in a single contained application. singletons cause issues in projects like web servers which are doing loads of things simultaneously and having a single shared resource and single shared piece of state can cause loads of problems, in a game its much easier to manage global state and singletons are a good way to keep global state from getting messy.
    I'd also like to point out that your SOs are basically singletons implemented in a different way and have all the same issues with global state, plus some idiosyncracies with how SOs are implemented. The main advantage of this solution is you have avoided dependency chains, which is a problem that's already solved (most games will instantiate all their singletons at game boot time and set up dependency chains then)
    Event based programming also has it's own set of problems and downsides. However this is a useful strategy I hadn't seen before so thank you for the informative video.

    • @wumpie5267
      @wumpie5267 2 ปีที่แล้ว

      Thanks, your comment helped

    • @dreamcatforgotten8435
      @dreamcatforgotten8435 ปีที่แล้ว +2

      There is a clear difference between non-Singleton SOs and Singletons [in the case of Unity, though I'm not sure what other game Engine also has SOs-- ]
      Domain Reload.
      Singletons require static referencing, so you must keep Domain Reload on to maintain a fresh state between Play Sessions in the Editor.
      SO have no such requirement since they are always considered loaded within the Editor, and when they are referenced [by a MonoBehaviour] in a Build.
      This difference means it is orders faster to test and iterate with non-Singleton SOs versus Singletons, especially as your project and assemblies grow larger.
      Edit: I'm being explicit about non-Singleton SOs, because you can implement SO's as Singletons. They're not mutually exclusive.

    • @user-uk9er5vw4c
      @user-uk9er5vw4c 3 หลายเดือนก่อน

      Singletons are commonly used in web development, especially with frameworks that support hooks

  • @jonathanjblair
    @jonathanjblair 2 ปีที่แล้ว +4

    I remember watching your videos when you had less than 1k subs. So glad you stuck with it and are closing in on 20k. Keep up the good work.

    • @samyam
      @samyam  2 ปีที่แล้ว +2

      Thanks so much for the support 😄

  • @ShinichiKudoQatnip
    @ShinichiKudoQatnip 2 ปีที่แล้ว +18

    Your explanation is just nothing short of amazing!!!! So much love for this 🤗

    • @samyam
      @samyam  2 ปีที่แล้ว +2

      Thank you!!!

  • @MagicPigGames
    @MagicPigGames 2 ปีที่แล้ว +3

    I like to make a Game version for in-game use. I.e. "ItemObject" is a scriptable object, and "GameItemObject" is the runtime variant. When creating the game version, JSON Utility can be used to clone the scriptable object data into the game version, which can then be changed and saved.
    I also use a repository object in the scene to reference the original Scriptable Object if needs be.

  • @theUSpopulation
    @theUSpopulation 2 ปีที่แล้ว +10

    Thank you for this! I have to go back and change a lot of things for my personal project, but you did a great job showing me that will be worth it!

  • @vornamenachname906
    @vornamenachname906 2 ปีที่แล้ว +17

    that has nothing to do with "scriptable objects" , its just the correct event handling.
    one last advice:
    use x?.invoke() with the questionmark to prevent exception's in case the delegate x is empty.

    • @vornamenachname906
      @vornamenachname906 2 ปีที่แล้ว

      *exceptions

    • @Kalahee
      @Kalahee 2 ปีที่แล้ว

      The point here was to use SO as data storage over playerprefs or singletons. Event handling is just an example

  • @Brioshie
    @Brioshie ปีที่แล้ว +2

    Although I've been using them already, you made me approach differently and optimize my project a lot! For example I have one scriptable object with a list of all my enemy behaviors and each enemy simply picks their properties from there. I can change only one asset now instead of 10s of prefabs

    • @samyam
      @samyam  ปีที่แล้ว +1

      Awesome!

  • @ERSmith
    @ERSmith ปีที่แล้ว +53

    I can't tell you how many times I've watched this video. So grateful you made such a beginner-friendly yet in-depth video. Thanks so much!!

    • @samyam
      @samyam  ปีที่แล้ว +5

      😁

  • @lekretka
    @lekretka ปีที่แล้ว +2

    Well, great video regarding explanation and graphics, but I have strong opinion against this approach and scriptable object architecture in general.
    1. While it can be designer friendly, it's error prone because you can forget to assign the event SO or someone can delete it.
    2. As a programmer it's really too much work to jump from code to editor back and forth.
    3. It creates the same problem as singleton bad example, you can't create more than one of these if you have multiple objects with Health logic. This is suitable for one player to many UIs, but it's not suitable for 100 units with 100 healthbars.
    Architecture imo should give you flexibility, but this approach requires separate Health handling for Player and other objects.
    I also think that bad examples to this approach comparison is quite unfair. There are much better ways to create health UI system without event SO approach.
    1. UI which grabs reference to Player which has "Action/UnityEvent HealthChanged" is pretty fine.
    2. Static EventBus which can be written in 20minutes is fine.
    3. Simple static field in Player or somewhere else with Action/UnityEvent is fine.
    Last two give you same decoupling between Player and UI.
    I'm glad you covered dependency injection topic, but for me it's default way to go and I would encourage more people using it.
    It solves all dependency/decoupling problems and let you build proper architecture.
    Sure it requires a framework, but if you are really at this point when simple approaches, I suggested above, don't fit you project it's probably time to learn Zenject.

  • @jaywha
    @jaywha ปีที่แล้ว +1

    As my first introduction to scriptable objects, this was concise and extremely helpful. Looking forward to your other vids

  • @SoaringSimulator
    @SoaringSimulator 2 ปีที่แล้ว +1

    There is a hidden important script code at 13:35!
    Having no references to other game objects is so difficult and at the same so important! In Unity is difficult to understand how references work inside a project. And if you hide or delete a game object with references that point to it you can get hidden bugs (null references) that do not pop up in the console.

  • @AlexBlackfrost
    @AlexBlackfrost 2 ปีที่แล้ว +3

    Very great tutorial, I like how you use bad examples first to explain what works and what doesn't.

    • @samyam
      @samyam  2 ปีที่แล้ว +2

      Thanks Alex!! Hope it helped 😄

  • @bobbob9821
    @bobbob9821 9 หลายเดือนก่อน +2

    Its my understanding that scriptable objects are best for storing read only data like item attributes and you don't want to be messing with changing values during runtime.

  • @lawsylawsy6593
    @lawsylawsy6593 2 ปีที่แล้ว +1

    Awesome video! Breaking everything down understandably for new coders! Beef it up by making a generic scriptable object event system and you have a totally decoupled code

    • @samyam
      @samyam  2 ปีที่แล้ว

      Great idea for another video! Thanks 🙂

    • @lawsylawsy6593
      @lawsylawsy6593 2 ปีที่แล้ว

      Happy to share code if you are interested? made the event system as a unity package for ease of sharing between our projects

  • @wspascoe
    @wspascoe 2 ปีที่แล้ว +1

    I remember trying this after the talk you mentioned but wasn't there something weird that happens when you actually build a game into an exe. I can't remember it's been awhile but still a great video.

  • @ironcladvr
    @ironcladvr 2 ปีที่แล้ว

    As I search to scriptable Objects, you've put out a video helping me understand them better.
    Many thanks Sam!

    • @samyam
      @samyam  2 ปีที่แล้ว

      Glad to help! :)

  • @rudrakpatra6579
    @rudrakpatra6579 2 ปีที่แล้ว

    Your way of explanation is so simple and easy to understand. Even before watching, I somehow know that I will be able to digest all of the concepts!

    • @samyam
      @samyam  2 ปีที่แล้ว

      That is my goal! Glad it is coming through 😄

  • @jl6723
    @jl6723 2 ปีที่แล้ว +1

    Personally, I like to have my managers use a global static dependency injector. This works well for having a manager talk with it’s subsidiaries in scene though.

  • @richardcabral9425
    @richardcabral9425 ปีที่แล้ว

    Wonderful, when I was learning SOLID I didn't think it would be so useful in game dev.
    Congratulations on your didactic

  • @JohnVanderbeck
    @JohnVanderbeck 3 หลายเดือนก่อน

    Personally I take it one step farther. First it's helpful to realize that the Unity editor IS a dependency injection framework. When you drag a SO onto a field in a MB you are setting up a dependency injection. Dependency injection and SO is not mutually exclusive. What I do it take it one extra step where there is a sort of registry for SOs based on a key. You can use strings, or whatever you like. I use string constants. Then, instead of hooking up the SO to the MB directly in the editor, you define what SO it needs via that key. At runtime it calls to the registry and asks for the SO by key and gets one returned.
    This mostly breaks the last hard dependency, leaving only the registry. It also allows you to build different registries if desired for testing or what not.

    • @samyam
      @samyam  3 หลายเดือนก่อน

      You can also use addressables to load at runtime via name forum.unity.com/threads/loading-scriptable-objects-as-addressables.1540706/

    • @JohnVanderbeck
      @JohnVanderbeck 3 หลายเดือนก่อน

      @@samyam Yeah that's an option, certainly viable. And you can even make different bundles for different things. It is however very heavy weight compared to a simple dispatcher where you just hook things up yourself for easy testing. Of course nothing says you can't use both options and even others.

  • @GrahamOfLegend
    @GrahamOfLegend 2 ปีที่แล้ว +3

    Such an excellent video! I really love scriptable objects and want more people to get into using em 🙌🏽🔥

    • @samyam
      @samyam  2 ปีที่แล้ว

      Thank you!!

  • @asadickens9353
    @asadickens9353 2 ปีที่แล้ว +2

    I don’t know why, but your videos are the only videos i don’t have to physically watch. I can listen to them and follow along easily enough!
    It might be the simple explanations and step by step process of how you think mixed with my general knowledge of unity.

  • @cinnamonmatcha9406
    @cinnamonmatcha9406 6 หลายเดือนก่อน

    After starting to consistenly use this I can say that it changed my life

  • @hanzofactory
    @hanzofactory 2 ปีที่แล้ว

    Thank you so much. I was really hung about how to use events with non-global data, and I managed to implement it thanks to this video!

    • @samyam
      @samyam  2 ปีที่แล้ว

      Glad it helped!

  • @jugger6228
    @jugger6228 2 ปีที่แล้ว

    OMG that's so awesome. Finally a solution without a bunch of annoying managers and singletons. Thank you very much :D

  • @kristianthaler6525
    @kristianthaler6525 2 ปีที่แล้ว

    Very clear explanation of why you should avoid dependencies, thank you.

  • @amikawi
    @amikawi หลายเดือนก่อน

    8:52 ScrawtVermillion the Melty Blood GOAT

  • @chocobo678
    @chocobo678 2 ปีที่แล้ว +9

    Hi, great video! You've pointed some important insights about SRP, decoupling and singletons, which is all great. The only thing that I actually dont agree is using SO as a middleware... you basically implemented a Publisher/Observer pattern but adding a SO, you could just make a simple Event Manager to handle messaging without it, the code would still be decoupled and you wouldn't have to make another SO for each corner case. Also what if multiple objects have to implement the same health logic? They cant just reference the same SO because they will always trigger this SO (e.g: you have character A and character B both referencing the Health SO. You have slide A and Slider B, both listening to Health SO. If character A decreases Health, both slider A and B would trigger)
    About persisting the data between scenes, I believe just serializing into json/binary would do the work

    • @timothysdug5832
      @timothysdug5832 2 ปีที่แล้ว

      Hi! Sorry to bother but could you (or anyone reading this) elaborate on why is that usin SO as a middleman is unnecesary? I'm just getting started with this part of unity, but i'm not a begginer. I used Singletons in very basic proyects and now I kinda understand that they are bad when the project gets big. I started reading about unity events and how powerful they are, and now I encountered this SO based architecture in many vids that use SO as channels between triggers and listeners, that sounds powerful but I get the same vibe as you, is it really necessary to implement a channel for each communication? Doesn't it get messy? How would you implement a middleman that does what an SO does without it?
      Thanks for reading, and sorry for my bad english i'm a little rusty.

    • @chocobo678
      @chocobo678 2 ปีที่แล้ว +5

      @@timothysdug5832 hi Tomás. The approach on the video is an abstraction to the Publisher/Observer pattern, which consists in decoupling entities that need to react to events in an application.
      Taking the example of the video, imagine that you have a Health object, and when the Health value is updated, different entities must react to it (e.g: the screen must shake if HP is subtracted , the UI must update the HP bar, the Death Logic must validate if the character is dead, etc.). In a highly coupled code, the HP script would manually call all these callbacks. This is bad because you delegate tons of responsabilities for a single class (HP), which means this class would have to know details of every class that should react to the HP Update, leading to a convoluted code and violating the Single Responsability Principle.
      The Observer pattern is a solution to ensure that a publisher (in this case the HP class) doesn't have to know every single observer (all the classes that must react to the HP update) and vice versa. In this pattern, the publisher just publishes a message/event "announcing" that something happened, and every listener subscribed to the message/event should react. The idea here is that none of these entities should know details of each other, the only thing connecting them is a Middleware that manages to assign publishers and observers.
      On the video approach, the middleware is a Scriptable Object, and I pointed on my first comment some of the problems in using SOs for that purpose instead of having a simple class managing the events.
      Of course that this is not written in stone, and there a multiple uses for SOs and for some cases it might be enough, but I personally wouldn't recommend it. If you're interested, this blog post contains a different approach to event handling that I really enjoyed and am currently using in personal projects:
      theliquidfire.com/2015/06/15/better-than-events/

    • @timothysdug5832
      @timothysdug5832 2 ปีที่แล้ว +1

      @@chocobo678 I can't thank you enough for taking that time to write such a complete answer. You've given me a lot to think about and read. I couldn't find a straight answer to this issue anywhere.
      In the end i'll use both SO architecture and managers for events just to fully understand what each of them mean.
      Again, thanks a lot.

    • @FullMe7alJacke7
      @FullMe7alJacke7 2 ปีที่แล้ว

      You're forgetting about how important it can be to make things in a designer friendly manner, therefore avoiding the need for changing any code.
      A designer can change these things by dragging SO files around.
      Also your mentioning of multiple instances being effected is easily fixable

  • @MaZyYTube
    @MaZyYTube 2 ปีที่แล้ว +1

    I worked on many different projects from small to big. We weregetting disappointed if the game also gets bigger. You have toooooooooo many scriptableobjects everywhere. You need to search, click here and there to finally work with them. Sometimes you also do not know where it is used. The question often is there "Do I need it.. can I delete it?". Often you would need your own Editor Tool Solution to see what is where connected. It is great for designers but if you start to make easy for your designer, why not use visual scripting?
    This also makes problem with buttons. Did you ever say "oops" OnClick still tries to invoke function but actually you removed a button? In big projects this happens very often. Thats why it is better to have Button reference in the code instead doing it via the inspector.
    That's why we used other event system. We now can use same thing without scriptableobject and with coding only. For instance we can do RegisterEvent(OnDamage). Everybody who register Damage will receive the Damage object. This works everywhere and has not dependency.
    The goods is IDE can show all references and connected scripts. You can wrote listener if you want to just as drag and drop component. Still works for designers as well.

  • @PeterMilko
    @PeterMilko 4 หลายเดือนก่อน

    I use dont destroy on load. For stuff like that i use delegates actions and unityevents. When you call them check for null event?.Invoke
    ()

  • @MickDarkstar1
    @MickDarkstar1 ปีที่แล้ว

    Greatest problem with being a software developer starting with Unity is the absence of IoC and Dependecy Injection. I´ve seen third party solutions, but this should be available out of the box.

  • @qin6409
    @qin6409 2 ปีที่แล้ว +1

    I come ti watch her video not only because of the tutorial, but also enjoyable voice

    • @samyam
      @samyam  2 ปีที่แล้ว

      Thank you :)

  • @mahee1931
    @mahee1931 2 ปีที่แล้ว +2

    Ha!!! All 3 bad examples can be found in my current project. Thank you for the great content.

    • @samyam
      @samyam  2 ปีที่แล้ว +1

      😂 Well every project is different and maybe another way makes more sense! But for larger projects and teams SO’s are a great option 👌

  • @Shineglow
    @Shineglow 7 หลายเดือนก่อน

    I've seen the original video, but I still don't see how I can implement this architecture in a game where there is more than one playable object. Imagine I have a multiplayer game, with a variable number of players, maybe 2-8. And many, MANY enemies, at least hundreds of them. My characters have different properties, such as health, weapons, speed. Do I need to use SO for each character variant? But what if I need more than one copy of any character for enemies or players?
    Help me understand.

  • @TextGuy
    @TextGuy 10 หลายเดือนก่อน

    Not sure if you still read comments here, but I am curious why not we just use a static class to solve the issues or is there any other benefits that comes with this SO + event architecture that a static class cannot solve.

  • @No_Ghosts
    @No_Ghosts ปีที่แล้ว

    How is the scriptable object pattern more de-coupled than the singleton pattern? Seems identical

  • @Barldon
    @Barldon ปีที่แล้ว

    Something that confuses me about this technique is; does this not create pretty tight coupling in of itself?
    If your player health lives inside an SO rather than the player itself, you run into the exact same scalability issue as a singleton does; it becomes incredibly difficult to change that SO significantly, you can't remove it if the health system changes, and you can't add another player without adding another SO and refactoring everything that depends on it. In essence, a SO kind of *is* a singleton - just one that doesn't live inside the scene.
    They're certainly one of the most powerful tools in Unity, but since watching that original talk this has always felt like a bit of an abuse of what they're intended for (That is, SO's are kind of meant to just hold persistent, usually constant data or logic that can be reused). If you took this approach to many things in a project, I just don't see how the amount of global state being managed wouldn't get out of hand.
    Some of these problems are solved by instantiating SO's at run time, as some people here have suggested. However, doing so you are then losing the core benefit of using the SO's in the first place, which is the ease of changing values.
    Just an observation on this method overall, super well made explanation and video nonetheless

  • @HenonChesserPlus
    @HenonChesserPlus 8 หลายเดือนก่อน

    Given this example, how would you handle several entities/gameObject who need their health managed? Would you have to create a new Health Manager SO for each entity?

    • @smir6096
      @smir6096 11 วันที่ผ่านมา

      i think you should just create a healthsystem class and make an instance of it for each entity

  • @Klayperson
    @Klayperson 2 ปีที่แล้ว +1

    Godot signals: "look what they have to do to mimic a fraction of our power"

  • @teleted3000
    @teleted3000 8 หลายเดือนก่อน

    Clearly explained. Well done.

  • @Luis96ef
    @Luis96ef 2 ปีที่แล้ว +2

    I was wondering if this approach would still be worth doing, for enemies for example; wouldn't you still need to spawn lots of instances of the scriptable object along with their monobehaviours?

    • @lvx969
      @lvx969 2 ปีที่แล้ว +2

      You wouldn't need this system for enemies. The main point here is the decoupling of UI from Player Health code. Enemies won't ever have this level of coupling between Health HUD elements. Enemy scripts can be designed independently from the player systems.

    • @akitoakito
      @akitoakito 2 ปีที่แล้ว +1

      It depends. Scriptable objects are just assets. You could create a simple enemy game object that has its AI and other starting stats stored in a Scriptable object. Then you could have a MonoBehavior reference it. That way you can easily swap the enemy AI to see which type of enemy works best in that given level. Unite 2016 has great talk about this.

    • @TheKr0ckeR
      @TheKr0ckeR ปีที่แล้ว

      @@akitoakito still doesnt answer the question about +100 enemies

  • @Link89110
    @Link89110 7 หลายเดือนก่อน

    A scriptable objet has a single reference to all game object in the scene, so what should i do if, for example, i have to create multiples enemies with the same base stats, but not the same actual health ?

    • @ProfParzival
      @ProfParzival 7 หลายเดือนก่อน

      Instances. Or make life easy and use Unity Atoms

  • @kobe_24
    @kobe_24 ปีที่แล้ว

    Aren't the scriptable objects writable only in editor?

  • @snek5385
    @snek5385 2 ปีที่แล้ว

    This is sooooo useful! Thanks!
    Wish to see more contents like this.

  • @emanueltejadacoste2250
    @emanueltejadacoste2250 2 ปีที่แล้ว +1

    Was this channel hide or something? How I didnt know about it? Amazing

  • @ragerungames
    @ragerungames 2 ปีที่แล้ว

    Great video.. Really liked the example problem you stated before and giving solutions to it!

    • @samyam
      @samyam  2 ปีที่แล้ว

      Thank you!!

  • @TheGugustar
    @TheGugustar ปีที่แล้ว

    In your example of an event subscription "middle-man", what would be the advantage of a Scriptable Object instead of a public static class?

  • @sadiqabbaszade4789
    @sadiqabbaszade4789 2 ปีที่แล้ว +2

    No god no, please, nooo! I appreciate the effort you put into making the videos, but I hate the idea. I used it before, it looks fine on paper, but when the number of events increase significantly, the project gets messy real quick. Again, I do appreciate your effort, but this is a terrific way to use SOs. One reason is as I explained above, and the other reason is you will have hard time tracing your event calls and listeners and stuff, whereas for regular c# events, the IDE lets you literally just shift+f12 to find references to your events. No need to go to individual objects, figure out what references what, and messy stuff like that. Use SOs wisely please.

    • @samyam
      @samyam  2 ปีที่แล้ว +1

      Thank you for your advice and input! I understand what you mean, there are pros and cons to different approaches, but I still think this is a valid way to organize projects. For a big project this method might create more overhead & make it harder to trace and debug, but for a smaller project it's very much worth exploring due to it's flexibility & organization.

  • @Dumbledork1337
    @Dumbledork1337 2 ปีที่แล้ว +1

    A youtuber sponsored by another youtuber? How the turn tables.

  • @sopinha-games
    @sopinha-games 5 หลายเดือนก่อน

    The video is great, i'm just having a little trouble implementing the scriptable objects in more complex mechanics. =/

  • @IlaiyaBharathi
    @IlaiyaBharathi 2 ปีที่แล้ว +1

    ooh.. can't wait...

  • @TheCecchino98
    @TheCecchino98 ปีที่แล้ว

    I'm wondering if it the scriptable object approach is still worth using if none of its data/events have to be used outside of one scene

  • @johnnewton7401
    @johnnewton7401 2 ปีที่แล้ว

    When the scene is reset with the scriptable object, how does the reloaded UI slider get the current health value? The event is only fired when the health is decreased so why is it updated when the scene is reloaded? I feel like I'm missing something. Thanks :)

  • @perabajadev
    @perabajadev ปีที่แล้ว

    I've got a question for you about what happens if I need to have multiple gameObjects with the same component, such as health Component and I need to modify the values differently for a player or some enemies. With ScriptableObjects wouldn't have a health value for each one, in fact I would only one

  • @omyb
    @omyb ปีที่แล้ว

    It's a very interesting video! Just one question: what's the pro of doing that instead of a classical event in the player script with the UI manager listening to it?

  • @PaperMouseGames
    @PaperMouseGames 2 ปีที่แล้ว

    Awesome video as always! I love scriptable objects and use them for everything I can 🤣

    • @samyam
      @samyam  2 ปีที่แล้ว

      Thank you!! 😄

  • @syriuszb8611
    @syriuszb8611 2 ปีที่แล้ว

    It's interesting, although I think that the leg work is done by the observer pattern.

  • @stuffstuffington39
    @stuffstuffington39 2 ปีที่แล้ว

    Wasnt the decoupling part of the solution entirely due to using events? Couldnt the same decoupling be done with the singletoln pattern? Fire and forget health change events and if no singleton is listening, no worries. Im probably mising something. Interesting to hear about all the different approaches one could take

  • @iCraftix
    @iCraftix 2 ปีที่แล้ว

    That health manager scriptable object is fine for a player, but how would you do to keep track of the health of hundreds of enemies that can spawn at runtime?

    • @pogudesu
      @pogudesu ปีที่แล้ว

      I believe it's not a good idea to make a health Scriptable Object for the enemies or any other object that requires a lot of instance.

  • @rogerbusquetsduran5596
    @rogerbusquetsduran5596 2 ปีที่แล้ว

    So you're wrapping the health value in an SO that can be modified by anyone...? sound kinda dangerous to me. Is there a way to prevent objects from modifiying its value? Or to give special access to some classes so they're able to modify it?

  • @HaniSharif
    @HaniSharif 2 ปีที่แล้ว

    This might be a silly question. But how do i use the same system to have a health decreasing and auto health regeneration after say. 5 seconds?
    Great tutorial btw. Helped me a lot!

  • @inquisitortr7930
    @inquisitortr7930 11 หลายเดือนก่อน

    Hi samyam can we apply this scriptable object for more than one player. You know we have one player here but what if we have 3 or 4. They will have different health values. Will just one scriptable object is enough or should we create multiple scriptable object to change health of players seperately? By the way awasome video thanks.

  • @madscientist338
    @madscientist338 2 ปีที่แล้ว

    Why use UnityEvent and add a NonSerialized attribute? You can just use Action or am I wrong?

  • @JesseTheGameDev
    @JesseTheGameDev ปีที่แล้ว

    So is your approach to pretty much never use Singletons? I hear a wide range of opinions on them

    • @samyam
      @samyam  ปีที่แล้ว

      They can be useful in some instances, and usually for smaller games and prototyping. They are hard to debug though, so use with caution.

  • @MaskedImposter
    @MaskedImposter 2 ปีที่แล้ว

    This is an interesting thing I hadn't thought of for scriptable objects, but I don't think it's one I'll use. For persistent scene data you could use a normal script (one that doesn't inherit from monobehavior). You could do singleton or just make it a static script, then you don't even have to worry about instantiating it. Plus it will get cleaned up automatically when the game closes.

    • @FullMe7alJacke7
      @FullMe7alJacke7 2 ปีที่แล้ว

      That approach often leads to an anti-pattern due to multiple classes end up depending on these static classes or singletons.

  • @akn638
    @akn638 2 ปีที่แล้ว +1

    This video as good as ryan hipple's talk. I immediately subscribed! Keep up the good work and thanks for the video :)

    • @samyam
      @samyam  2 ปีที่แล้ว +1

      Thanks so much!! 🙂

  • @ferhatkaya9217
    @ferhatkaya9217 2 ปีที่แล้ว

    Samyam i need help! İ downloaded Starterassets. İ deleted mesh renderer of PlayerArmature and put my character obj into "geometry". Everything was fine,animations fine, i was able to put animations.. but i cannot apply animation rigging. Actually İ do but it gives errors. Do you have any idea about it?

  • @bitmammothOG
    @bitmammothOG ปีที่แล้ว

    So would DI be good for external dependencies or loading databases/caching, then using scriptable objects to pass around data between those dependencies without creating tighter coupling? (Great Video!)

    • @bitmammothOG
      @bitmammothOG ปีที่แล้ว

      I mean can't we use DI to inject scriptable objects that already have the data availability/persistence deliverables filled by the di and updated by the game? Then move the data from SO's to db/cache using entities when persisting?

    • @bitmammothOG
      @bitmammothOG ปีที่แล้ว

      Hmm only on client side, it would still need to be serialized on serverside, then it would need to update the SO's on client side from the deserialized data. Interesting :)

  • @akn638
    @akn638 2 ปีที่แล้ว

    I have enemies which use same implementation. When i deal an enemy it lowers scriptable object's value but also changing health other enemies. Can you help?

    • @dreamcatforgotten8435
      @dreamcatforgotten8435 ปีที่แล้ว

      For things like enemies, they should have their own instance of a ScriptableObject that acts as their data.
      The reason why the Player has a use for Asset-level interactions is because the Player is designed to be a persistent entity, as well as other things that will be reused throughout the game (Items, UI, etc)
      Do you have a need for the same enemies to always exist throughout your scenes, in the same fashion as the Player?

  • @DarkzarichV2
    @DarkzarichV2 2 ปีที่แล้ว

    Hmm
    Honestly I feel like it's better for me to stick with C# events instead of Unity events. And I saw a lot of professionals follow this too.
    What do you think?

    • @samyam
      @samyam  2 ปีที่แล้ว

      C# events are faster and use less memory, but Unity events integrate directly with the editor allowing drag and drop. I think the difference in performance shouldn’t be too bad, I like the UnityEvent due to ease of use. Up to you :)!
      stackoverflow.com/questions/44734580/why-choose-unityevent-over-native-c-sharp-events

  • @AngryApple
    @AngryApple 2 ปีที่แล้ว

    This Singleton thing instead of Monobehaviour... is this something that is already in C#?
    I always did Singletons differently 🤨

    • @DynastySheep
      @DynastySheep 2 ปีที่แล้ว

      That's just a separate class that samyam made with its own function to handle Singletons. If you look at 6:35, there is a Static T Instance (T meaning generic).

  • @steveh3206
    @steveh3206 2 ปีที่แล้ว

    Really helpful videos, thanks!

    • @samyam
      @samyam  2 ปีที่แล้ว

      Thank you :)

  • @alexf3946
    @alexf3946 2 ปีที่แล้ว

    This is magic, thanks!

  • @coderious4568
    @coderious4568 2 ปีที่แล้ว

    Excellent tutorial!

    • @samyam
      @samyam  2 ปีที่แล้ว

      Thanks so much!!

  • @goodpersonff
    @goodpersonff 2 ปีที่แล้ว

    hlo can u teach me about state machines plz

  • @FLATLINEGameDevChannel
    @FLATLINEGameDevChannel 2 ปีที่แล้ว

    But Scriptable Object only can edit in Edior

  • @alexanderlazarev3006
    @alexanderlazarev3006 2 ปีที่แล้ว

    After these videos saying how awesome scriptable objects for decoupling I always have one question:
    Unity explicitly said that you can only set and change Scriptable Objects in Editor, and it doesn't work in deployment builds. So what's the point of having constant value of health that you can't change when you build game? Or am I the only one missing something???
    Just google "Unity scriptable object"
    "When you use the Editor, you can save data to ScriptableObjects while editing and at run time because ScriptableObjects use the Editor namespace and Editor scripting. In a deployed build, however, you can’t use ScriptableObjects to save data, but you can use the saved data from the ScriptableObject Assets that you set up during development.

    • @empty5013
      @empty5013 2 ปีที่แล้ว

      you can have mutable values inside a scriptable object that are changed and if you mark them as non serialised they won't be saved by the engine. the values are still editable in a deployed build as a scriptableobject is ultimately just a C# class with some special logic that is created at application startup, and can be referenced by objects through the unity drag and drop interface.
      tldr you can edit the values in a runtime build you just cant save SOs or expect them to be persistent between game launches.

  • @lordkakabel76
    @lordkakabel76 2 ปีที่แล้ว

    Bless you! I have paid for courses that are less informative.

  • @EverScrolls
    @EverScrolls 2 ปีที่แล้ว

    I thought the data in Scriptable Objects were read-only once you build your game...?

  • @neozoid7009
    @neozoid7009 2 ปีที่แล้ว +1

    Awesome 👍

  • @weckar
    @weckar ปีที่แล้ว +1

    Why a scriptableobject though? Why not just a basic script? Non-monobehaviour?

  • @alingogoase8886
    @alingogoase8886 2 ปีที่แล้ว

    Did something change about SO? I remember trying to use them to store some data but they act differently for unity and builds. The values restart when for example you exit the build on your phone. Has anyone tried this recently on a build? If I remember correctly, I tried to keep the player gold as a value in the SO but the value keeps restarting when starting the game (without setting the value or something), I mean I understand that it is not the same usage scenario but just curious about the workflow.
    Thank you.

    • @AliceLoverdrive
      @AliceLoverdrive 2 ปีที่แล้ว +2

      SOs aren't serialized outside of Unity Editor, you'd have to implement actual serialization yourself. They do retain their data between scene reloads.

    • @alingogoase8886
      @alingogoase8886 2 ปีที่แล้ว

      Oh, ok, now I get it. Thank you very much!

    • @justinwhite2725
      @justinwhite2725 2 ปีที่แล้ว +1

      This is the correct behaviour. You can’t use SOs to save data between sessions.
      For some reason, they keep their values in the editor when you end play mode, which gives the illusion that they do in production. This is a huge oversight, in my opinion. They should work more like components and reset when you stop post mode.

    • @dreamcatforgotten8435
      @dreamcatforgotten8435 ปีที่แล้ว

      @@justinwhite2725
      You are right if you only mean their default behavior, however--
      You can use SOs to save data between sessions if you use JSONUtility.ToJson to save the SO to a JSON string and write the string to a file at a persistent data path, and load it later with JSONUtility.FromJson / FromJsonOverwrite.
      Also, for your last comment, I half-agree. I think there should be a setting to allow for either reloading between Play Sessions OR not... that way it is explicit.
      That said, I love their default behavior now. It is absolutely excellent to have what feels like an Editor-based static value that can be modified and have its value persist after Play mode. Messing with Animation curves is very fun with this feature.

  • @HelPfeffer
    @HelPfeffer 2 ปีที่แล้ว

    I enjoyed the video :)
    New sub

    • @samyam
      @samyam  2 ปีที่แล้ว

      Thanks!

  • @TheSixoul
    @TheSixoul 2 ปีที่แล้ว +1

    Singletons aren't necessarily bad it's just new programmers depend on it too much. There's a time and place for it. This is well done but it only goes about as in depth as the Unite talk. The issue with the talk is it doesn't go into more depth in the various examples they talked about. Good video and I hope there's more depth coming.

  • @LeatherBootsJohnson
    @LeatherBootsJohnson 2 ปีที่แล้ว

    Awesome video

    • @samyam
      @samyam  2 ปีที่แล้ว

      Thank you!!

  • @aa31749
    @aa31749 ปีที่แล้ว

    The best

  • @slowfuse
    @slowfuse ปีที่แล้ว

    you are still bound to an object for this to work, it just so happens to be a scriptable object now. meh. it works fine as a monobehaviour on smaller projects.

  • @EnderElohim
    @EnderElohim 2 ปีที่แล้ว +2

    4:34 not really because a simple if(!exist) return will solve null issues
    5:39 also cool idea to not name it as Instance and name it Manager so Karens would know who to talk with
    Also screw those that looks down to singletons. They are bad game developers and should not listened. Singleton is a tool. Just like others. Also if you gonna have singleton on your game you not gonna have any place where that not exist. It is bad excuse to be honest. Also even it is not exist you can create it on demand. Again depend how you use it. Maybe you dont need singleton if you not using constantly.

  • @leddoo
    @leddoo 2 ปีที่แล้ว

    just have the slider fetch the health value from the player (or "health manager") every frame. no need for any event handling complexity.
    there is literally only one slider in the scene, you won't be able to measure a performance difference.

    • @samyam
      @samyam  2 ปีที่แล้ว

      The slider is a simple example to demonstrate, once you have more objects to check on the screen checking in update can become cluttered and hard to manage. Event based programming makes it so that you only receive notifications once values have changed, cleaning up the code by a lot.

    • @leddoo
      @leddoo 2 ปีที่แล้ว

      @@samyam I'm with you that event based programming can be a good idea here, but in my opinion, it has *nothing* to do with code cleanliness and if anything makes the code harder to understand. Let me explain:
      Like you said, event based programming is about *when* code gets executed (only when the value is changed). But it is still the *same code* that gets executed: `slider.set_value(health)`.
      If you put that code in `update`, you only need one line of code. That's it.
      With events, you need that line of code + a callback function + two calls to register and deregister the callback. And on top of that, the code breaks if someone accidentally removes the callback or resets the listeners on the observable (you have an implicit invariant that the callback remains registered while the slider is live).
      Maybe you haven't thought about it this way. I hope you can agree that the second case is more complex.
      So why do I agree that event based programming *can* be useful?
      1) performance - obviously.
      2) dependencies: putting the code in update can actually lead to a subtle bug: if the slider's update is called before the player's health is changed, it will only reflect that change on the next frame. event based programming takes care of executing the code in the correct order.
      So if the performance hit is negligible and the execution order works out (eg: because ui objects update after game objects (don't know unity - would hope that they gave you some kind of guarantee like that)) i'd say using events is strictly worse due to its increased complexity.

  • @CoolinarGameDeveloper
    @CoolinarGameDeveloper 2 ปีที่แล้ว +6

    Oh, my God, that's a terrible way to go. If anyone has seen this video, PLEASE forget everything it says. The scriptable objekt is used to store STATIC data that is used as a configuration or setting. Don't use them in rantime as mono bech. And of course they should not have public fields for writing data.

    • @jumpkut
      @jumpkut 2 ปีที่แล้ว

      I had the same feeling although I don't understand it well enough to explain why yet. Could you explain why exactly this is a bad idea?

    • @zerotoanime3953
      @zerotoanime3953 2 ปีที่แล้ว +1

      @@jumpkut Personally I have never done this. I have used Classes to instantiate my functions because classes dont have dependencies in the same way that she is presenting it. Classes can be called by using "using MyClass" at the top of your script. Now all of your functions can be called externally from a library. And in the event you need and edge case for a specific way a function needs to be called and react differently. Just make that function then or add some kind of if statement that catches those rare exceptions to be used. It seems convoluted to call from static singletons because why use something static when the game state is dynamic. Also I write to text files and read them when it comes to health/inventory. I make singleplayer games so for me security on file alternations is not important issue for me in my case. So I call a read function to set all the last saved data. I can save and write to the files at anytime. And when it comes to UI passing over to another scene. I'm curious as to why she doesn't make it so that the UI isn't required to do a calculation on a damage script. UI should be dependent on the calculation not the other way around. If i was her, id put a if statement and check if the value of the health bar has changed. If it has changed then update the health bar. That way all the UI script checks is player health and that's it. Give it a null reference check to prevent errors and your good.

  • @smir6096
    @smir6096 11 วันที่ผ่านมา

    scriptable objects are NOT persistent

  • @ElboxD
    @ElboxD 2 ปีที่แล้ว +5

    I'm so in love with you...r work.

    • @samyam
      @samyam  2 ปีที่แล้ว +1

      Good save

  • @VergilxUA
    @VergilxUA 2 ปีที่แล้ว

    Don't do this please.
    Treat ScriptableObjects as read only data. Otherwise you're openning a whole new bag of bugs.

    • @NukeCloudstalker
      @NukeCloudstalker 2 ปีที่แล้ว

      SO's as readonly is very nice. It's a great way to let designers and artists author data for wide ranges of visuals and behaviour, super easy to slot in, swap and modularize.
      But yea, it's a pain when people can edit them. Runtime-instantiated SO's are good for that though! You can create copies of SO's and distribute that, and let that be modified for the session - only good for things you don't want persisted, if you don't want the headaches associated with read/write SO's.

  • @StephenWebb1980
    @StephenWebb1980 2 ปีที่แล้ว

    yeah scriptable objects as the controller in the model view controller design pattern is absolutely perfect in the generation of editor tools programming - and usage in the ECS or Mono based systems. I personally LOVE using scriptable object to manage data. I'll create a model class like 'Character', a view class like 'CharacterEditor' and finally a Controller class called 'CharacterDatastore' which extends a generic DataManager class that reads/creates/modifies the scriptable object asset. All this gets serialized. All extends a single BaseObject class that every character, item, stat etc has access to. When I need to access the data in game, I'll either set it up to be used as a property / field in a Monobehavior or as part of the data used by ECS objects so the same data can be used to drive object functionality in different game data interaction methodologies. Check out my twitch.tv/stephenwebb1980 channel to see how I use this technique to build video games

  • @kwombat5306
    @kwombat5306 6 หลายเดือนก่อน

    ofcourse its woman making this kind of video XDDDD

  • @512Squared
    @512Squared ปีที่แล้ว +21

    Another approach is a static class to hold actions that can then be invoked anywhere. That likewise doesn't have to sit on a game object of worry about being destroyed. But decoupled code can make it difficult to track event chains, since a publisher has no record of its subscribers. You have to use your search parameters in your code IDE to tracks event chains. Spaghetti is horrible, but so is a partially obscured event system.

  • @JoSke633
    @JoSke633 2 ปีที่แล้ว +9

    Awesome vid! You went through the concepts in a very digestable and clear way, adding some sweet graphics :)
    I think this approach really shines for making tech designer-friendly tools, which you mentioned at the end. If working with someone who can move around in Unity and iterate on mechanics and gameplay with these events without diving into code, it can be a huge productivity boost and fuel creativity while keeping the code decoupled. If just working with code, then I don't think it pays off compared to a regular event bus in C#.

  • @MTweedC4
    @MTweedC4 ปีที่แล้ว +6

    I've seen the talk you're referencing ... and am very happy to found someone who goes and explains it in more detail! Thanks!!