Build Your Own Dependency Injection in less than 15 Minutes | Unity C#

Поділитися
Вставка
  • Опубліковано 7 січ 2025

КОМЕНТАРІ • 173

  • @git-amend
    @git-amend  Рік тому +13

    Hi everyone! I hope you find constructing a lightweight Dependency Injection framework helpful! There are many ways to implement DI in Unity, and this is one I think is the easiest to digest. The solution to the challenge at the end of the video is included in the code repo (Injecting into Properties). Spend some time considering what features you would add to this implementation to make it bulletproof and more powerful.

    • @shantanumaskeri
      @shantanumaskeri 2 місяці тому

      In your injector class, and for injecting public fields, is there a way to make them not appear in the inspector, without using the [HideInImspector] attribute?

  • @dabmaster6874
    @dabmaster6874 Рік тому +37

    Your content brings a challenge to my learning journey. Your tutorials look more like software engineering than the usual Unity tutorials. I stumbled upon your state machine implementation and I was amazed. Subscribed and waiting for more and more content.

    • @git-amend
      @git-amend  Рік тому +3

      Thank you so much! Cheers!

  • @nickr9160
    @nickr9160 Рік тому +21

    Brilliant content, brilliant channel. Keep up the great work, it's a breath of fresh air seeing some upper-intermediate content, seems to be tricky content to find and yours is presented really concisely

    • @git-amend
      @git-amend  Рік тому +2

      Much appreciated! Thank you!

  • @Runesun
    @Runesun 10 місяців тому +4

    Your content is exactly what I've been hoping for as someone who's been doing tons of enterprise dev and just starting with Unity. Big big thank you! Also - why do I get the feeling that you've given more than your share of dev talks at either a local user group or something larger. You break things down and demonstrate extremely well. Been taking notes on that soft skill AND the game dev specific stuff.

    • @git-amend
      @git-amend  10 місяців тому +1

      Thanks for the kind words! I don't give too many talks, except at work!

  • @nexgen.graphics
    @nexgen.graphics Рік тому +6

    15 minutes of so much so much so much information. phew!!. I need to take a breath, watch it again and again to grasp this. A must need thing up my sleeve. Thanks for this tutorial.

  • @endihidir2087
    @endihidir2087 Рік тому +5

    I am using VContainer library for dependency injecton. This tutorial helped me understand how the system works behind the scenes. Thank you very much for this Awesome content 🙏🏼

  • @TheMathias95
    @TheMathias95 Рік тому +5

    As a software engineering getting into unity, these videoes are fantastic. From my experience it's very rare, even difficult to find basic programming principles from the software industry being covered in unity videoes.
    I've definitely been used to dependency injection and was baffled this is not a part of unity by standard.
    I really don't understand how the most common practices of developing scalable and modular code is not a priority amongst the avaerage Unity tutorial channel. I feel bad for beginners ending up in a world of issues due to bad design.
    Granted your videoes might be difficult from a beginners point of view, I think you a have pretty good balance, keeping the information relevant and understandable for the beginner.

    • @git-amend
      @git-amend  Рік тому +2

      Thank you! Always encouraging to hear that kind of feedback. Cheers!

  • @angelomoro8430
    @angelomoro8430 5 місяців тому

    This is a solid way to present Depency Injection in such a short time. I was struggling a bit to understand and use the DI systems in the market (like VContainer) used in a project I'm working on. After watching the video, and writing down the content presented in the video, I can say it works like a gem. Thank you so much!

    • @git-amend
      @git-amend  5 місяців тому

      You're welcome, thanks for the comment!

  • @mrcallum1995
    @mrcallum1995 Рік тому +2

    Love this series of tutorials! I wanted to say I was expecting you to build upon your service locator from last video to build this system, since that and DI are opposite sides of the same coin. That system was super flexible and allowed for scoping. Either way this is an interesting way of providing services through attributes, instead of the usual registration / binding workflow found in Zenject or Microsoft DI. Nice one!

    • @Utamaru56
      @Utamaru56 Рік тому

      Looks pretty similar to Zenject though because IDependencyProvider is basically an installer

    • @git-amend
      @git-amend  Рік тому +2

      Thanks! It would be nice to eventually build a system that can handle all the best features of both implementations and then include some graph theory to validate all dependencies too. That gave me an idea for a future video! Cheers!

  • @KeyboardKrieger
    @KeyboardKrieger Рік тому +1

    This is just really good stuff. As a software engineer i like this advanced stuff. It's not the standard in unity tutorial world

    • @git-amend
      @git-amend  Рік тому +1

      Thanks, I appreciate that!

  • @jumpjumpdiegaming
    @jumpjumpdiegaming Рік тому +5

    As usual an amazing video with a lot of detail. I was wondering though, perhaps you could spend a few minutes at the beginning really unpacking what each concept is, for example, explaining what dependency injection really does/is. Otherwise, an amazing video! 😊

    • @git-amend
      @git-amend  Рік тому

      Thanks for your comment! I'll keep that in mind!

    • @jumpjumpdiegaming
      @jumpjumpdiegaming Рік тому

      @@git-amend just would love to hear your thoughts and explanations as an experienced dev!

  • @ekekw930
    @ekekw930 Рік тому +1

    Im always looking forward to your videos on Sunday!

  • @AstralNostalgia
    @AstralNostalgia Рік тому +3

    Please more videoa baout DI . Thanks , this is a gem video...I need a little more touch to understand ..but it is very cool!!!

    • @git-amend
      @git-amend  Рік тому

      Thank you, I will

    • @feildpaint
      @feildpaint Рік тому +1

      ​@@git-amend As a more novice programmer, I'm also having some difficulty understanding the uses of this framework. I think seeing concrete examples during runtime with things actually happening in a game would help a lot. Thanks for the great video anyways!

    • @AstralNostalgia
      @AstralNostalgia Рік тому

      it is exccellent and you use tecnical glosary, such as service, provider, inyector , etc, I should really try to make a cheat sheet in my block to understand that glosary..related to my curiosity to wikipedia and some other reading online.... it is hard and I still learning to implement in unity ,however thank you so much for the purpose of this video, I think this concept is a must for become a good programmer and stop the godot migrations.

  • @cheesecakenl1980
    @cheesecakenl1980 Рік тому +1

    Ah yes... Short and concise. Right up my alley.

  • @PetersExcapades
    @PetersExcapades 9 місяців тому +1

    i strive to be as good as you one day good sir, i really like how you architect your code!

    • @git-amend
      @git-amend  9 місяців тому

      I appreciate that!

  • @trex6867
    @trex6867 11 місяців тому +4

    Please record more detailed video about dependency injection and unit testing

  • @ramonmelo6427
    @ramonmelo6427 2 місяці тому

    Quite good! Thanks for sharing

    • @git-amend
      @git-amend  2 місяці тому

      Glad you liked it!

  • @rutchjohnson
    @rutchjohnson Рік тому +1

    I will say, you have some great content. But I'm not sure who these videos are for. One question that I have is why should I use this system and what real world problem does this solve/make easier for devs? I look for this question to be answered at the beginning of every tutorial video I watch. It sets the tone and direction for the rest of video. Thanks for the great content! :)

    • @git-amend
      @git-amend  Рік тому +5

      Thanks for your comment. The inversion of your dependencies (aka Inversion of Control) is a key part of object oriented programming and of course is the D in SOLID.
      Using a Dependency Injection system or a Service Locator are ways to achieve Dependency Inversion where your dependencies are not tightly coupled to the objects and systems which depend on them, making it easier to manage, extend, and test large and complex Unity projects.
      If you haven't yet encountered a situation where you needed to refactor or scale up a project significantly, the benefits of this system might not be immediately apparent, but they become invaluable in larger, more complex development scenarios where tightly-coupling all your game objects and systems together can lead to a cascade of problems if one part needs to change.
      If time permits, I'll create a real world example before the next video on this topic. Cheers!

    • @rutchjohnson
      @rutchjohnson Рік тому

      @@git-amend oh nice! Thanks for the explanation. Yeah I think I wouldn’t be alone in this but up front stating here is the value in this xyz concept is important so that I have a reason to use what you are teaching us. Again love your teaching style and expanding my knowledge of Unity and C# :)

    • @sisus_co
      @sisus_co Рік тому +4

      Another way to understand the benefits of using a DI framework in Unity, is that it can pick up where serialized field-based DI stops working:
      1. Cross-scene references.
      2. Interface support.
      3. Injecting dependencies manually in code (essential for unit tests).
      4. Dynamic values (e.g. inject different objects based on current platform).
      5. Easily swapping a service to a different one for all components in all scenes and prefabs.

  • @artcadedev
    @artcadedev 3 місяці тому

    11 seconds in and subscribed already

  • @OskGame
    @OskGame 25 днів тому

    i have some questions
    1. how to distinguish between player or enemy ICharacter interface (i have idea is provide("Player") and provide("Enemy), using inject also, what do you think
    2. To remove the value when provide like interface, so how to assign null to them, when i destroy game object they still have value
    3. if gameobject like player will delete and load for each screen, should use ServiceLocator or DI, because i need to register and unregister
    thank you for sharing.

  • @kevin41307
    @kevin41307 11 місяців тому

    mind blowing content!!

  • @MafiaSniper
    @MafiaSniper 8 місяців тому

    Great video!
    Although too difficult for me😌I think I should start with the theoretical side first.

    • @git-amend
      @git-amend  8 місяців тому +1

      Sure! One step at a time!

  • @흑심품은흑마법사
    @흑심품은흑마법사 5 місяців тому

    Im really thank you for your post...
    is really really helpful to me

    • @git-amend
      @git-amend  4 місяці тому

      You are most welcome

  • @alexsolovev228
    @alexsolovev228 2 місяці тому

    Hey, great video as always! What are your thoughts on implementing a custom MonoBehaviour object like InjectableMonoBehaviour and running the reflection process to inject fields in Awake method as an alternative to scanning the scene for objects to inject? This would also eliminate the problem with additive scene loading as well as injecting objects instantiated dynamically. I know it is less elegant but I think it could work for some cases.

  • @ugurkarabulut8598
    @ugurkarabulut8598 Рік тому

    I've just learned zenject and u post this :D

    • @git-amend
      @git-amend  Рік тому

      Haha.. well congrats! Most people find Zenject a bit overwhelming at first, so that's a big accomplishment! This must seem trivial!

  • @emz6133
    @emz6133 4 місяці тому

    What would be your go-to approach for dependency management in Unity? Building your own lightweight DI framework? So far I've seen only you suggest that (I'm not saying it's not a good solution). For MonoBehaviours I use serialized fields, but I don't know what to use for standard C# classes. And I assume if I pick one approach for standard classes I should use it in MBs also and drop serialized fields (for providing dependencies) completely, right? What are my options? There is Service Locator, but people generally don't recommend it. Concerning DI frameworks, Jason Weimann and Jason Storey say that you should only use them if your dependencies become too complex and you cannot manage them on your own. I'm building a mobile MOBA game, so that would be a medium or large size project, I'm not sure how to classify it.

    • @git-amend
      @git-amend  4 місяці тому

      I would say that even if you don't introduce DI from the start you should program with the principle of Dependency Inversion in mind so that your code is as loosely coupled as possible. In Unity it's almost impossible to have completely decoupled code due to heavy use of Serialized Fields and so on, but where possible you should be using appropriate levels of abstraction and supplying dependencies to the classes that need them in some fashion. If you keep the D in SOLID in mind while you are programming, and you find later that you need to use a DI Framework or a Service Locator, it will be easier to introduce than if you are creating your dependencies inside the class that depends on them. That's harder to do with MonoBehaviours because you can't have a ctor, but with plain C# classes it should always be the case. For me personally, I would use some form of inversion of control from the start, either my own solution on a small project, or on a bigger project I would probably choose either Reflex or Sisus Init Args from the Asset Store.

  • @unitydev457
    @unitydev457 8 місяців тому

    Hi, this is an incredible tutorial! I had two questions. first is a syntax i was unsure of:
    at around 9:30 you did something that im a bit unclear on. line 65: var resolvedInstances = requiredParameters.Select(Resolve).ToArray();
    How does Resolve know the type if its not passed in?
    Does Linq's Select pass the type of requiredParameters as if you called Resolve(requiredParameters)?
    2) Am I understanding correctly that in this implementation all providers and dependencies need to exist as game objects in scene at start? The inject method only gets called once right? So this wouldn't account for game objects instantiated during runtime? Or did I misunderstand

    • @git-amend
      @git-amend  8 місяців тому

      Thanks! To directly answer your first question: Yes, LINQ's Select method passes each element (Type in this case) of requiredParameters to the Resolve function, effectively behaving as if you called Resolve on each individual Type contained in requiredParameters. This allows the Resolve method to attempt to fetch an instance of each type from the registry.
      For your 2nd question, yes this system is meant to exist in your game on game objects and runs only one time, so it's meant for injection on things that exist from the beginning of your game. If you need more power than that, you can either inject factories into things like spawners so that you can use them when instantiating new objects, or you can feel free to fork and extend the library as you see fit... or you might feel comfortable enough to use a more complex and powerful 3rd party framework.

    • @unitydev457
      @unitydev457 8 місяців тому

      @@git-amend Thanks for the answers! Ive been working on my own dependency injection system and still haven't quite sorted out how I want to handle runtime dependencies but it seems like factories are a really solid option to get around the no constructor issue.

  • @mifrpost
    @mifrpost 3 місяці тому

    Hey, this is an awesome tutorial, I learn a lot from all your videos, so thank so much for your contant. One thing I
    m struggling with is Injecting into abstract classes or parent classes that aren't attached to a GameObject. Would anybody have an idea how to work with injection here? Thank you

  • @rofu8096
    @rofu8096 Рік тому

    My gratitude is beyond words. Thank you very much for all the information you provided.

  • @vigscodes
    @vigscodes Рік тому

    Great video thanks for sharing!

    • @git-amend
      @git-amend  Рік тому

      Thank you! You're welcome!

  • @okhalo_dev
    @okhalo_dev Рік тому +1

    Thank you for the video!
    I have a question: will the 'auto' injection only occur when the game starts (upon the awakening of the injector singleton)? So, are injectables only fed if they are present in the initial open scene at the beginning? Why not use something like "[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] or scene loaded event" to iterate each time a scene is opened? Also, what happens with runtime-instantiated objects? Should I 'manually' call 'Inject(instance obj)' on the singleton, passing it as an argument in my factory or use Service Locator?
    (I'm using additive scenes system and can't add an injector singleton to each scenes)

    • @git-amend
      @git-amend  Рік тому +3

      Thank you! Glad you like the video. To answer your questions: Yes, this injection system runs when the Scene starts for all injectables present in the scene at that time. You can perform injection on demand from within the scene for objects created at runtime, just pass 'this' into the Inject method.
      Using RuntimeInitializeOnLoadMethod is a viable choice - but it also has limitations. This attribute is for when the runtime is starting up and loading the first scene - it does not automatically trigger methods to run again when additional scenes are loaded additively. Keep in mind that going this route means that you cannot execute any code in the scene before Injection happens - for example, you might want to perform some logic and validation in the Awake methods of various providers, and move the injection to be performed during the Injector's Start method.
      If you can't have an Injector present in each scene due to a limitation of your additive scene system, using the SceneManager.sceneLoaded event may be your best option.

  • @devphil0
    @devphil0 Рік тому +1

    Great stuff as always. A few things I wanna say: A comment mentioned combinding service locators and this DI framework so I'm very interested to see what you'd come up with for that.
    I see other DI frameworks use lifecycle integration for Update and so on, so I wonder how easy it would be to integrate into this framework? Probably just a matter of defining interfaces for such services and making sure to instantiate and resolve them, I assume. Similar to how VContainer does it.
    And lastly, a little critique on your editing, i would find it great if you could linger on the code you just wrote a little bit longer. Sometimes I find myself confused where a debug statement came from because the code was shown for like 1 second. I know I can pause and return but it would improve the overall clarity of the video.

    • @devphil0
      @devphil0 Рік тому

      And another thing I will probably do myself is build an instantiation system that automatically resolves dependencies on a new prefab.

    • @devphil0
      @devphil0 Рік тому

      And ANOTHER thing i think would be pretty good too, since I've been pretty bootstrapping pilled lately, I would probably modify the system to run either on subsystem registration or on scene loading to make sure it all happens before any Awake call. Changing execution order works too, but why do that when you can make sure that 100% of the time your system will run before anything else.

    • @git-amend
      @git-amend  Рік тому +5

      Thanks for the comments. Implementing lifecycle is not too hard to do in both the Service Locator and this DI system, and I would do it with interfaces as well. There will likely be more videos on DI coming up to dive a bit deeper into these areas, and others that come up in comments. Cheers!

    • @gaelp.5847
      @gaelp.5847 2 місяці тому

      @@devphil0 All your points are very valid but once you have all that, you basically made zenject X)

  • @yashaswiification
    @yashaswiification Рік тому

    Thank you!! For teaching us

  • @TheKr0ckeR
    @TheKr0ckeR 8 місяців тому

    re-watched your video and completely understood how DI framework works. Thanks a lot for that. What makes me think is which classes should we provide? Like Manager classes, or even player? I think its all about providing super-classes or "single" classes. Are there any scenarios where we provide "an enemy instance"? I really got how this framework works, but i am confused about what to provide. For example a wave controller class where it spawns - despawns to get information if wave spawn ended? And a game state class where it controls the game state itself. Are those a good example to provide so that others can easily react by game state, or wave endings like UI etc.

    • @git-amend
      @git-amend  8 місяців тому +1

      A good way to think about that is to consider classes that are dependencies for another class. So, if your AI Agent depends on a Blackboard, you can provide that using Inversion of Control for example - either Dependency Injection or a Service Locator. Whenever one class depends on another class that is a 'system' (not some static creature or item in your game world) you should attempt to provide it in a decoupled manner, and you should implement either a base abstract class for it or an interface. This way, if you were to completely change the Blackboard implementation, the classes that use it don't have to change.

  • @mask7376
    @mask7376 10 місяців тому

    Injection or Singleton. Which one ?

  • @OrekiBurd
    @OrekiBurd Рік тому

    Im kind of a beginner, trying to understand the video. Whats k_bindingFlags do in 4:43 actually binding flags in general

    • @git-amend
      @git-amend  Рік тому

      That's a great question! BindingFlags in C# are used to define how reflection searches for members (methods, fields, etc.) of a class. In the context of this example, the combination of these flags specifies that the reflection should look for both public and non-public instance members. So, in this video, when reflection is used with these BindingFlags, it will scan through all instance members (fields, methods, etc) of a given class (in this case each MonoBehaviour we have found in the scene), regardless of their access modifiers (public or non-public).
      learn.microsoft.com/en-us/dotnet/api/system.reflection.bindingflags?view=net-8.0

  • @friedcrumpets
    @friedcrumpets Рік тому

    I was looking into building one of these a while ago but when it came down to it the reflection and attribute tagging put me off and leaned me towards a ServiceLocator allowing monobehaviours to grab dependencies on Awake. With unity specifically it feels more logical as with DI it usually requires a bit more of a standardised framework to pull off. If not everybody on the team is familiar the DI can easily get thrown out of the window quickly.
    Are there any performance drawbacks to be aware of in using this?
    Brilliant video as always, really great to see this kind of thing covered in such an easily digestible way. Keep them coming :D

    • @git-amend
      @git-amend  Рік тому +2

      There will always be some overhead when using reflection, and while it's worth noting that Unity's performance with reflection has improved over time, the more classes you have to search through in this system, the more of an impact it will have. You can optimize this of course, and one way would be to gather services used together into an abstract factory instead of injecting them all seperately. You can also add a bit more funcitonality to this system and begin to cache services for different scopes, similar to what we did with the Service Locator so that we have global and scene level dependencies. This will be the topic of an upcoming video.
      Other considerations - right now the system is only looking for dependencies provided from MonoBehaviours. It also does not perform any validation - you might want to apply some graph theory to verify completeness.
      Like all systems, there is always room for improvement, and we'll continue to dive into these kinds of things. Thanks for your comment!

  • @sagrgywejhxcvx
    @sagrgywejhxcvx 4 місяці тому

    I use a service locator and it works perfect, why is DI better?

    • @git-amend
      @git-amend  4 місяці тому

      Maybe watch the video about D in Solid. The short answer is that with a Service Locator, you will always be coupled to the Service Locator. With DI, your classes are not coupled to anything. They are both good options though in my opinion. ua-cam.com/video/JSqE4C7ZZos/v-deo.html

  • @cl8lf1wm8b
    @cl8lf1wm8b 8 місяців тому

    what are downsides of DI in your opinion? in a context of unity I mean

    • @git-amend
      @git-amend  8 місяців тому +1

      It can lead to increased complexity, potentially complicate debugging and potentially affecting runtime efficiency if you were to start injecting beyond game start up. These are all things that can be mitigated, however.

  • @Cloud-Yo
    @Cloud-Yo 10 місяців тому

    This is awesome stuff...now, what kind of overhead does all this have if you were to spam injection over a larger project? Either way, I got to see how little baby attributes are born...nature is amazing.

    • @git-amend
      @git-amend  10 місяців тому +1

      There will definitely be some startup cost which would scale based on size; on a bigger project you might want to consider a more powerful DI solution like Zenject. Glad you liked it!

    • @Cloud-Yo
      @Cloud-Yo 10 місяців тому

      @@git-amend Got it, I think its called Extenject now after 2020. Thanks to this video I feel better prepared to tackle that tool. p.s. got properties working as well. Thanks again!

  • @very_old_dog
    @very_old_dog Рік тому

    The only question I was chasing during the whole video is what's the purpose of all that stuff? What are the benefits?

    • @git-amend
      @git-amend  Рік тому

      Thanks for your comment. A Dependency Injection framework is one way of fulfilling the 'D' in SOLID. It's purpose is to decrease the amount of tight coupling between your systems so that if you need to change one system you don't have to refactor everything that depends on it, or serialize any references to that system - instead the system is provided as needed, and if you program to interfaces you can simply provide a different system without changing any other code in your project.
      If time permits, I'll include a real-world example in the next video to further illustrate this concept.

    • @very_old_dog
      @very_old_dog Рік тому

      @@git-amend got it. Thank You for clarification. Indeed it would be great to see real world example.

  • @endihidir2087
    @endihidir2087 11 місяців тому

    There's something I'm curious about. Why did you choose to make the FindMonoBehaviours() and IsInjectable() methods static? Because they work even when they are not static?

    • @git-amend
      @git-amend  11 місяців тому

      Generally speaking, it is a best practice to mark public and private methods that do not require state as 'static', and your IDE may even hint you to do this. There are a few reasons for this; one is that it makes your code self-documenting - it indicates to future you or anyone else reading your code that this method does not use any instance members and is pure utility. There is also a small compile time benefit in C# which you can read about here: stackoverflow.com/questions/135020/advantages-to-using-private-static-methods

    • @endihidir2087
      @endihidir2087 11 місяців тому +1

      @@git-amend I understand, thank you very much for the source. In general, it is recommended in some places not to use static structures unless absolutely necessary, for many reasons, such as memory consumption (especially for mobile games), lifetime, difficulty in testing, etc. That's why I'm a bit confused, to be honest.

  • @doancatphu6912
    @doancatphu6912 9 місяців тому

    nice content. I wanna ask that can we have only one singleton manager script managing others manager and combining with dependency injection to make our project become maintainable and scalable. If i dont use singleton in my project, what alternatives will be the best. Thanks!

    • @git-amend
      @git-amend  9 місяців тому +1

      Technically that is possible, but it's often not practical. The biggest issue with this is that having just one singleton managing all other systems becomes a bottleneck, both in terms of performance and maintainability, if not carefully managed. It is in a way introducing a new form of tight coupling because every module in your program would be tightly coupled to this singleton object. I would lean towards keeping the project modular instead of routing through one god-object. On the other hand, there are some advantages to injecting a singleton, such as breaking the dependency on the singleton using injection, which makes your code much more testable.

    • @doancatphu6912
      @doancatphu6912 9 місяців тому

      @@git-amend cause i found out that it is not good when you abuse singleton too much in your project. I asked others and was told to manage managers in only one singleton. So in sum up, i can combine singleton and DI to make less dependency, right?

  • @ZombieChicken-X
    @ZombieChicken-X 10 місяців тому

    Hi I'm new to architecture coding (I think that's sorta what this is?) I'm trying to organize my projects more instead of having 1 singleton with references to all my classes. Does it make sense to use dependency injection for things like manager classes? For example if I have a MonoBehaviour class that handles a majority of the UI or a player animation handler, can those be services injected into other scripts?

    • @ZombieChicken-X
      @ZombieChicken-X 10 місяців тому

      Im thinking this could work? Id be able to inject PlayerInputHandler and PlayerAnimationHandler into my main Player class on an initialization method, am I understanding this correct or is there a better approach to what I need

    • @git-amend
      @git-amend  10 місяців тому +1

      That's the general idea. Dependency Injection and Service Locator, are ways to achieve Dependency Inversion - which is to supply the dependencies for a given class at runtime without tightly coupling the class to the dependencies and/or without having to create the dependencies inside the class that requires them.

    • @ZombieChicken-X
      @ZombieChicken-X 10 місяців тому

      Thanks man I really like your videos and am binge learning with them. Btw what do you use to edit them?@@git-amend

  • @lukass1604
    @lukass1604 Рік тому

    Keep up the videos👍

  • @Typtick
    @Typtick Рік тому

    I have a problem. If we have IEnvironmentSystem as an interface and create 2 different classes that implements this interface and both of these classes want to provide the injection content from itself with the Provide Attribute. Registery will have two same type Key and cause an exception.
    Is that intentionally planned in the video like is it something you expect us to figure out or am I having a problem?

    • @git-amend
      @git-amend  Рік тому

      This is intentional - this system is just an MVP. Feel free to extend it as much as you like. If you don't want to extend it to directly support that type of behaviour, you could provide a factory instead and let the classes that depend on the interface type call the appropriate factory method (or one factory method with a param) to get the correct concrete type. So EnvironmentFactory could support multiple IEnvironmentSystem implementations.

    • @Typtick
      @Typtick Рік тому

      @@git-amend
      Thank you for your answer!
      I've been on Unity for 2 years and seen countless of tutorials but yours are super under-rated. Especially it helps me out since these patterns and architectural approach was quite lacking on my end for Unity. Please feed us with the content!

  • @mongreldesigns9195
    @mongreldesigns9195 Рік тому

    I am learning so much from your tutorials, thank you.
    I do have one (possibly stupid) question, I can't for the life of me figure out where the attributes are assigned.... how does this...
    public sealed class InjectAttribute : Attribute { }
    Get identified as [Inject]

    • @git-amend
      @git-amend  Рік тому +3

      That is a very reasonable question, one that I asked myself long ago. Actually I'm surprised nobody else has asked that yet. In C#, attributes are defined using their names followed by the word "Attribute".
      When you define public sealed class InjectAttribute : Attribute { }, you can use it as [Inject] in your code. This is a shorthand provided by C#, where the "Attribute" suffix can be omitted when you're using the attribute.
      You can also use the full name if you wanted to like [InjectAttribute] - both ways are correct and functionally equivalent.

    • @mongreldesigns9195
      @mongreldesigns9195 Рік тому +1

      @@git-amend That is where my head was but i could not find anything to validate the theory, probably because I thought it was a unity thing.
      Thank you again, your videos are just above where I feel I am at, making them perfect to progress!

  • @gladiko2364
    @gladiko2364 Рік тому +1

    That was cool, b-but where/when would you ACTUALLY use this?

    • @git-amend
      @git-amend  Рік тому +1

      You would use it in situations where different components or systems in your Unity project need to share or use common services or objects without tightly coupling them together. It reduces the dependencies between components, leading to a more decoupled architecture.
      An example would be injecting references to a localization service into various components. You might have 20 game objects that need to call the localizationService.translate() method, so they all must keep a reference to this service. With DI, you don't tightly couple game objects to their dependencies by dragging and dropping a reference to this service in every game object, instead it's injected where needed.
      You would also use it when testing, you could inject a service that always returns the same result so that you aren't testing end-to-end, you are testing just the component under test.

    • @laserbean00001
      @laserbean00001 Рік тому +1

      @@git-amend This is really confusing. Why don't you just use a static class and static method to run those stuff instead of the object reference?

  • @TheKr0ckeR
    @TheKr0ckeR Рік тому

    Great guide, I always have a pre-judge against DI in Unity. How often do you use DI framework in your projects? I find myself pretty confused against changing the code structure and putting DI Third party framework on top of everything, like WContainer. I feel like I am fightining with unity when i use DI framework

    • @git-amend
      @git-amend  Рік тому +2

      I can relate to that, especially if you are trying to introduce DI after you've already been developing your project for a while. For me, I do not use it in every project. It's more important to adhere to the Dependency Inversion principle than how you go about it. Some coupling in Unity is unavoidable of course. In many cases, just programming with the concept of Dependency Inversion in mind is enough to save yourself a lot of grief in the long run. For me personally, it would be a choice to use a DI framework (or a Service Locator) or not from the start of the project rather than trying to shoehorn it in later on.

    • @TheKr0ckeR
      @TheKr0ckeR Рік тому +1

      @@git-amend Great answer. Thanks man. Still DI is not in my top 3 in Unity :D But your video really made me understand how to achieve DI without third party.

    • @sisus_co
      @sisus_co Рік тому +1

      In my experience the trick to making a DI framework not feel like it's fighting against Unity is to spend some effort to integrate it well with the Inspector. Just like with serialized fields, it should be easy to locate injected services just by looking at the Inspector, and if you want to replace one, you should be able to just drag-and-drop some other instance in.
      I think that after this change, most of the usual complaints that people have about DI frameworks in Unity become non-issues.

    • @TheKr0ckeR
      @TheKr0ckeR 8 місяців тому

      @@git-amend What is your most-preferred communication type between high-level systems like GameState, controller etc. Singletons, Service Locators or DI like zenject etc? I have started a new game where i have game controller which holds the data for "Game status like pregame, warmup, and stuff." Player will be ready and inform about game state, so that spawner can start spawning by that delegate. To communicate between those, how would you approach to that solution in best practise scaleable way?
      1- Player will click ready button
      2- Game state should react to that by making the game status/ready.
      3- After game is ready, spawner will spawn the wave.
      So how would you communicate between those? My game is full of this type of communications and i dont know how to approach to that as best case.
      My approach would be,
      Player will have a delegate OnReady, and will call it from button.
      Game state serializes the player as a field, and subscribe to ready event.
      Zombie Spawner will somehow need to know game state, and subscribe to OnGameStateChange event, but singletons? Service locators? DI? Or game state will also know about Zombie Spawner and will simply call, spawner.StartWave(); or another, zombie spawner will know about gameState as serializeField.. I want to choose between them but i cant decide. I want to make it as a best practise and follow along.
      I am really wondering your approach here.

    • @git-amend
      @git-amend  8 місяців тому +1

      @@TheKr0ckeR I would use an Event Bus to handle the situation you are describing: multiple disparate systems need to coordinate based on specific events initiated by the Player. This is especially useful if you are working with multiple scenes, but a good solution for any project.

  • @lost.250
    @lost.250 11 місяців тому

    As far as I can see the system only injects at Awake, what about classes that are created dynamically?

    • @git-amend
      @git-amend  11 місяців тому

      That's correct - can only fit so much into 15 minutes! Feel free to fork the library and add more functionality. Perhaps, if enough people ask, I will make a video about extending this in the future.

    • @lost.250
      @lost.250 11 місяців тому

      @@git-amend It would be great to see it! Keep up the good work, I really appreciate your videos :p

    • @dawidkubiak5642
      @dawidkubiak5642 10 місяців тому

      @@git-amend
      Great video! Extending your DI system to support dynamically created classes would be incredibly beneficial for many of us working with Unity.
      Considering the interest it has already sparked, a follow-up tutorial could be highly valuable for the community.
      Looking forward to possibly seeing more on this topic!

  • @wisemiceclique4498
    @wisemiceclique4498 Рік тому

    Ok, so what if I want to inject something in other scene. Let’s say that we have classB component in the next scene. Just adding the attribute won’t work in this case. What’s the best way to manage this?

    • @git-amend
      @git-amend  Рік тому +1

      This Injector component works on a per scene basis. In this implementation it handles the dependencies for the scene that it belongs to. Unless you are trying to persist it across multiple scenes with a [DontDestroyOnLoad] attribute, it will work for every scene you put it into by finding and then injecting all the dependencies that have been provided in that scene.
      In the next video we are going to start talking about scope and make this system more powerful so that it can handle dependencies that need to exist across multiple scenes.

    • @redboss5429
      @redboss5429 Рік тому

      Would like to use this as replacement for scriptsble object singletons so i can have it across scenes! Awaiting a part 2🎉

  • @oswaldcobblepot764
    @oswaldcobblepot764 Рік тому

    I wish i had this 5 years ago :D

  • @h.y-chen
    @h.y-chen 7 місяців тому

    old dotnet guy but new to unity here, after I learn the basic of Unity ,the first thing I do is find a way to use DI in unity since it make things way more easier, then I come across this video , but since the reflection is expansive so if build it my self it become nasty with lot expression trees or IL generation , I'm curious if you have attempted to integrate Microsoft.Extensions.DependencyInjection with Unity? The video made it seem achievable, and I'm interested to know if you already tried it

    • @git-amend
      @git-amend  7 місяців тому +1

      I have not tried that - but to be honest it sounds very interesting. If you do look into it, please let me know, I'd love to see what you come up with!

    • @h.y-chen
      @h.y-chen 7 місяців тому

      @@git-amend I'll try but need look more deep into UnityEngine first , the DI impl in your video it get all gameobject when excuting the script , so I guess it won't work if create game object dynamiclly?

    • @git-amend
      @git-amend  7 місяців тому

      @@h.y-chen That's correct, all dependencies in this 'lite' system are expected to be present at the start. A potential workaround is create a Factory and make that the dependency that will then create GOs at runtime. Otherwise you may need to look into some kind of registration system and verify a dependency graph too. I added a few improvements in the following video, but nothing quite that complex.

  • @ekekw930
    @ekekw930 Рік тому

    Does this remove the need of Singletons? I have a save and load system that is implemented as a singleton with DontDestroyOnLoad. Can I refactor this to a service that will be used by DI? How does it handle different scenes?

    • @git-amend
      @git-amend  Рік тому +2

      DI doesn't necessarily remove the need for singletons, but the short answer is that generally yes, you probably can refactor your singleton save and load system into a service for use with Dependency Injection (DI). You mention that your system requires it to be scene independent. This particular implementation of DI is very simple, so you would want to look at combining the features used in either the Service Locator video or the EventBus video to bootstrap a class that would handle your injections in a more powerful way, including on a per scene basis or at a global level. As mentioned in a few other comments, this will be the topic of a future video, so stay tuned!

    • @ekekw930
      @ekekw930 Рік тому

      @@git-amend Thank you for the answer! What I currently did to "solve" this was to change the Singleton class to use the DontDestroyOnLoad method. I then added all the needed Provider scripts to my prefab that also has the Injector script. This way they are all persistent over multiple scenes. Not sure if I am happy with this solution and if it is even a good one, any thoughts?

    • @ekekw930
      @ekekw930 Рік тому

      @@git-amend Also you mention a SceneLoader video but I cannot seem to find it?

    • @git-amend
      @git-amend  Рік тому +2

      @@ekekw930 One thing that comes to mind is that you may need some kind of system to provide and inject services that are required after your Injector class runs it's Awake method for the first time - because it won't be run again in your scenario. In Scene 2, if you have some new dependency that didn't exist in Scene 1, it won't be found. This is why you might need to upgrade this system in the same manner as the Service Locator video which could find all your Providers in all scenes and register them on a per scene basis. You could then inject dependencies on scene load, and also maintain global dependencies throughout such as a save/load system. We'll get into this in a future video, but feel free to try it yourself - just make sure you commit your work first! 😜

    • @git-amend
      @git-amend  Рік тому +1

      ​@@ekekw930 Sry.. brain not working - I meant Service Locator - ua-cam.com/video/D4r5EyYQvwY/v-deo.html

  • @muhammadzubairirshad6724
    @muhammadzubairirshad6724 Рік тому

    Just Amazing

  • @nuin99
    @nuin99 Рік тому

    Whats your workflow for having UI decoupled?

    • @git-amend
      @git-amend  Рік тому

      It depends. In many cases where you just want to display information, like a HUD, then Scriptable Objects make great Mediators. For example, values to be displayed for a Player's health and mana can be stored in Scriptable Objects and read by any components that need them. This simple approach is sufficient for many games as far as UI goes. However, many projects require a bit more interaction, and for that I would use either an Event Channel or an EventBus. There are videos on both those topics on this channel. Because UI varies from project to project, there is no real one size fits all solution.

    • @nuin99
      @nuin99 Рік тому

      @@git-amend yes actually I have been using scriptable objects, but I keep thinking about a situation where for example you have a variable amount of entities that need UI, like if you decide to make your game multiplayer, then the approach wont work. Ill check out the things you mentioned, thank you

  • @查理-k5s
    @查理-k5s 9 місяців тому

    Thanks for this tutorial, but don't compress it to too short, slow down so we won't need to pasued often.

  • @laserbean00001
    @laserbean00001 Рік тому

    Okay. From what i understand, instead of creating a class instance each time, the provider creates one and injects it into anything that needs it. It really seems like this can be solved with a static class.

    • @git-amend
      @git-amend  Рік тому +5

      The reason people choose DI over static classes is that calling static methods creates tight coupling with the classes that call them. In contrast, DI promotes loose coupling by allowing you to interchange implementations without altering the dependent code.

    • @laserbean00001
      @laserbean00001 Рік тому +3

      @@git-amend it would be great if you could give us some real examples where using this is better than the other methods. Cause this looks like a lot to set up.
      (Currently in my unity journey, i've learnt about all sorts of programming patterns with the most recent one before this vid being the observer pattern. So I really want to make sure i learn things correctly.)

  • @LuRybz
    @LuRybz Рік тому

    i really like the content that you bring, your thumbnails, titles are really attractive to me but I feel that inside the video the content is too abstract and hard to follow.
    Often there is plenty of complex systems already in the code, lots of presumptions and knowledge before and there is lack of analogies.
    I can follow your videos but I feel there is a lot of space for improvement and this can bring more visibility to your channel.
    I hope this sounds to you like a constructive feedback and not an complaining.
    Thank you for sharing your knowledge.

    • @git-amend
      @git-amend  Рік тому

      Thanks for your comments, your feedback is always welcome.

  • @jacobs.7925
    @jacobs.7925 Рік тому

    Any specific reason to call singleton's namespace Malevolent? 😂😅

  • @Andrew-pd2ci
    @Andrew-pd2ci Рік тому

    Hey mate, sorry for bothering you. Can I somehow have a chat with you, I kinda need help with a specific sort of stuff plus I have a sort of a deal for you. At least will be nice to have a little talk. I can't find a way to message you directly or your email :(. I will tell you about myself(spoiler, I am a game dev) and what I am working on atm.
    Btw, thanx for your content, the most professional coding content about game dev as a topic on UA-cam, thank you for the high-quality content

    • @git-amend
      @git-amend  Рік тому

      At this time, I don't have the bandwidth for chats per-se but if you have a question about something you don't want to post here, you can message me on Twitter - link is in the description.

    • @Andrew-pd2ci
      @Andrew-pd2ci Рік тому

      @@git-amend
      I tried to, but idk why I am not allowed to text anbd there....
      Will be okay to chat under that comment then ?

    • @adammyhre
      @adammyhre Рік тому

      @@Andrew-pd2ci Settings prevent DMs until you get a follow back. Try again.

  • @retrospective9425
    @retrospective9425 Рік тому

    Hi there....is there any email from you? Any way to make any contact?

    • @git-amend
      @git-amend  Рік тому

      You can DM me on Twitter, link is in the description.

  • @xopabyteh
    @xopabyteh Рік тому

    Although I feel that DI is an excellent design pattern, i feel like it is an overhead for game making, as it's kinda performance heavy.

    • @git-amend
      @git-amend  Рік тому

      I agree, it's good to understand and suitable for some projects, but overkill for some.

    • @nasterofpuppets
      @nasterofpuppets Рік тому

      There are many ways to do DI, including using serialized fields, pure DI and source generators, so using the design pattern is not necessarily performance heavy at all. In fact, converting runtime GetComponent calls to serialized fields is a common performance *optimization* tactic in Unity :)

  • @edward3190
    @edward3190 Рік тому

    This seems like Singleton pattern. Instead of [Inject] ServiceA, [provide] ServiceA, why not ServiceA.GetInstance, ServiceA.SetInstance, you can drag and drop different ServiceA between active and inactive hierarchy, so that only the one in active hierarchy would SetInstance as itself during OnEnable().

    • @git-amend
      @git-amend  Рік тому +1

      Thanks for your question! Using an instanced singleton for dependencies creates tight coupling because the game object directly relies on a specific, concrete implementation. While you aren't coupled directly to the service, you still require a reference to the singleton in order to call it's public Get and Set methods. A DI system removes this coupling.

  • @HexGrimm
    @HexGrimm Рік тому

    You currently have only a partial implementation of Dependency Injection. When creation is delegated to a framework, it becomes the framework's responsibility to ensure that the entire graph is disposed of in the correct order and at the appropriate time. As it stands, this approach violates the RRR pattern.

    • @sisus_co
      @sisus_co Рік тому +3

      Components in Unity are already automatically released (destroyed) when their scene is unloaded. As such, it's not necessary for the DI framework to contain any custom code for figuring out when to release them.
      class Service : MonoBehaviour, IService, IDependencyProvider
      {
      [Provide] // Register
      IService IDependencyProvider.ProvideService() => this; // Resolve
      void OnDestroy() { ... } // Release
      }
      Unity is its own beast, with most of the object graph configuration usually taking place in edit mode, and being resolved by Unity automatically, so many traditional DI framework patterns don't necessarily transfer to Unity 1:1.

  • @nuin99
    @nuin99 Рік тому

    Way too fast my brain is imploding

  • @rechnight
    @rechnight 6 місяців тому

    Maybe something I'd change is instead of injecting everything from the Injector on Awake, is to have the MonoBehaviours call the Injector on themselves.

    • @git-amend
      @git-amend  6 місяців тому +1

      I don't think you could call that an Injector anymore. If MonoBehaviours start calling the Injector on themselves, it shifts the responsibility of dependency management back to the MonoBehaviours. What you are describing sounds a bit more like a Service Locator, where classes ask a central registry (the Service Locator) for their dependencies, rather than having them injected by an external Injector. There's a video about Service Locators on the channel too.

    • @rechnight
      @rechnight 6 місяців тому

      @@git-amend Thanks for the clarification! I thought of the Monobehaviours calling the Injector on themselves so that entities instantiated later on could also have the dependencies injected. How could this be solved with your Injector?

  • @-Engineering01-
    @-Engineering01- 6 місяців тому

    Too much overhead to make a DI framework even a little one. I'd prefer to buy that via asset store. Thanks 😊

    • @git-amend
      @git-amend  6 місяців тому +1

      If you are looking for a great DI tool that is easy to use from the store, I recommend this one. There is a free version as well.
      assetstore.unity.com/packages/tools/utilities/init-args-200530?aid=1101lw3sv

    • @-Engineering01-
      @-Engineering01- 6 місяців тому

      @@git-amend I bought it immediately thank you !