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

  Рет қаралды 15,299

git-amend

git-amend

Күн бұрын

Пікірлер: 172
@git-amend
@git-amend 11 ай бұрын
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 29 күн бұрын
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 11 ай бұрын
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 11 ай бұрын
Thank you so much! Cheers!
@nickr9160
@nickr9160 11 ай бұрын
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 11 ай бұрын
Much appreciated! Thank you!
@Runesun
@Runesun 9 ай бұрын
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 9 ай бұрын
Thanks for the kind words! I don't give too many talks, except at work!
@TheMathias95
@TheMathias95 11 ай бұрын
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 11 ай бұрын
Thank you! Always encouraging to hear that kind of feedback. Cheers!
@nexgen.graphics
@nexgen.graphics 11 ай бұрын
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.
@git-amend
@git-amend 11 ай бұрын
Glad you enjoyed it!
@endihidir2087
@endihidir2087 10 ай бұрын
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 🙏🏼
@git-amend
@git-amend 10 ай бұрын
Great to hear!
@jumpjumpdiegaming
@jumpjumpdiegaming 11 ай бұрын
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 11 ай бұрын
Thanks for your comment! I'll keep that in mind!
@jumpjumpdiegaming
@jumpjumpdiegaming 11 ай бұрын
@@git-amend just would love to hear your thoughts and explanations as an experienced dev!
@KeyboardKrieger
@KeyboardKrieger 11 ай бұрын
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 11 ай бұрын
Thanks, I appreciate that!
@angelomoro8430
@angelomoro8430 4 ай бұрын
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 4 ай бұрын
You're welcome, thanks for the comment!
@mrcallum1995
@mrcallum1995 11 ай бұрын
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 11 ай бұрын
Looks pretty similar to Zenject though because IDependencyProvider is basically an installer
@git-amend
@git-amend 11 ай бұрын
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!
@AstralNostalgia
@AstralNostalgia 11 ай бұрын
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 11 ай бұрын
Thank you, I will
@feildpaint
@feildpaint 11 ай бұрын
​@@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 11 ай бұрын
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 11 ай бұрын
Ah yes... Short and concise. Right up my alley.
@git-amend
@git-amend 11 ай бұрын
Haha great!
@ekekw930
@ekekw930 11 ай бұрын
Im always looking forward to your videos on Sunday!
@git-amend
@git-amend 11 ай бұрын
Yay! Thank you!
@trex6867
@trex6867 9 ай бұрын
Please record more detailed video about dependency injection and unit testing
@rutchjohnson
@rutchjohnson 11 ай бұрын
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 11 ай бұрын
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 11 ай бұрын
@@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 11 ай бұрын
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.
@PetersExcapades
@PetersExcapades 8 ай бұрын
i strive to be as good as you one day good sir, i really like how you architect your code!
@git-amend
@git-amend 8 ай бұрын
I appreciate that!
@emz6133
@emz6133 2 ай бұрын
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 2 ай бұрын
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.
@okhalo_dev
@okhalo_dev 11 ай бұрын
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 11 ай бұрын
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.
@alexsolovyov3322
@alexsolovyov3322 21 күн бұрын
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.
@artcadedev
@artcadedev 2 ай бұрын
11 seconds in and subscribed already
@ramonmelo6427
@ramonmelo6427 19 күн бұрын
Quite good! Thanks for sharing
@git-amend
@git-amend 19 күн бұрын
Glad you liked it!
@TheKr0ckeR
@TheKr0ckeR 6 ай бұрын
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 6 ай бұрын
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.
@devphil0
@devphil0 11 ай бұрын
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 11 ай бұрын
And another thing I will probably do myself is build an instantiation system that automatically resolves dependencies on a new prefab.
@devphil0
@devphil0 11 ай бұрын
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 11 ай бұрын
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 22 күн бұрын
@@devphil0 All your points are very valid but once you have all that, you basically made zenject X)
@mifrpost
@mifrpost 2 ай бұрын
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
@MafiaSniper
@MafiaSniper 7 ай бұрын
Great video! Although too difficult for me😌I think I should start with the theoretical side first.
@git-amend
@git-amend 7 ай бұрын
Sure! One step at a time!
@rofu8096
@rofu8096 10 ай бұрын
My gratitude is beyond words. Thank you very much for all the information you provided.
@git-amend
@git-amend 10 ай бұрын
You are very welcome
@unitydev457
@unitydev457 7 ай бұрын
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 7 ай бұрын
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 7 ай бұрын
@@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.
@friedcrumpets
@friedcrumpets 11 ай бұрын
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 11 ай бұрын
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!
@endihidir2087
@endihidir2087 10 ай бұрын
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 10 ай бұрын
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 10 ай бұрын
@@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.
@mask7376
@mask7376 9 ай бұрын
Injection or Singleton. Which one ?
@Typtick
@Typtick 11 ай бұрын
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 11 ай бұрын
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 11 ай бұрын
@@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!
@kevin41307
@kevin41307 10 ай бұрын
mind blowing content!!
@git-amend
@git-amend 10 ай бұрын
Thanks again!
@흑심품은흑마법사
@흑심품은흑마법사 3 ай бұрын
Im really thank you for your post... is really really helpful to me
@git-amend
@git-amend 3 ай бұрын
You are most welcome
@sagrgywejhxcvx
@sagrgywejhxcvx 3 ай бұрын
I use a service locator and it works perfect, why is DI better?
@git-amend
@git-amend 3 ай бұрын
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. kzbin.info/www/bejne/gITUdmd5bL-NpdU
@Cloud-Yo
@Cloud-Yo 8 ай бұрын
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 8 ай бұрын
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 8 ай бұрын
@@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!
@TheKr0ckeR
@TheKr0ckeR 11 ай бұрын
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 11 ай бұрын
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 11 ай бұрын
@@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 11 ай бұрын
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 6 ай бұрын
@@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 6 ай бұрын
@@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.
@ПавлоК-з9н
@ПавлоК-з9н 11 ай бұрын
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 11 ай бұрын
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.
@ПавлоК-з9н
@ПавлоК-з9н 11 ай бұрын
@@git-amend got it. Thank You for clarification. Indeed it would be great to see real world example.
@cl8lf1wm8b
@cl8lf1wm8b 7 ай бұрын
what are downsides of DI in your opinion? in a context of unity I mean
@git-amend
@git-amend 7 ай бұрын
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.
@gladiko2364
@gladiko2364 11 ай бұрын
That was cool, b-but where/when would you ACTUALLY use this?
@git-amend
@git-amend 11 ай бұрын
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 11 ай бұрын
@@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?
@ugurkarabulut8598
@ugurkarabulut8598 11 ай бұрын
I've just learned zenject and u post this :D
@git-amend
@git-amend 11 ай бұрын
Haha.. well congrats! Most people find Zenject a bit overwhelming at first, so that's a big accomplishment! This must seem trivial!
@lost.250
@lost.250 10 ай бұрын
As far as I can see the system only injects at Awake, what about classes that are created dynamically?
@git-amend
@git-amend 10 ай бұрын
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 10 ай бұрын
@@git-amend It would be great to see it! Keep up the good work, I really appreciate your videos :p
@dawidkubiak5642
@dawidkubiak5642 9 ай бұрын
@@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!
@vigscodes
@vigscodes 10 ай бұрын
Great video thanks for sharing!
@git-amend
@git-amend 10 ай бұрын
Thank you! You're welcome!
@doancatphu6912
@doancatphu6912 7 ай бұрын
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 7 ай бұрын
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 7 ай бұрын
@@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?
@mongreldesigns9195
@mongreldesigns9195 11 ай бұрын
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 11 ай бұрын
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 11 ай бұрын
@@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!
@wisemiceclique4498
@wisemiceclique4498 11 ай бұрын
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 11 ай бұрын
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 10 ай бұрын
Would like to use this as replacement for scriptsble object singletons so i can have it across scenes! Awaiting a part 2🎉
@ZombieChicken-X
@ZombieChicken-X 9 ай бұрын
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 9 ай бұрын
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 9 ай бұрын
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 9 ай бұрын
Thanks man I really like your videos and am binge learning with them. Btw what do you use to edit them?@@git-amend
@h.y-chen
@h.y-chen 5 ай бұрын
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 5 ай бұрын
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 5 ай бұрын
@@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 5 ай бұрын
@@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.
@yashaswiification
@yashaswiification 11 ай бұрын
Thank you!! For teaching us
@git-amend
@git-amend 11 ай бұрын
My pleasure!
@OrekiBurd
@OrekiBurd 11 ай бұрын
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 11 ай бұрын
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
@nuin9937
@nuin9937 11 ай бұрын
Whats your workflow for having UI decoupled?
@git-amend
@git-amend 11 ай бұрын
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.
@nuin9937
@nuin9937 11 ай бұрын
@@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
@ekekw930
@ekekw930 11 ай бұрын
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 11 ай бұрын
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 11 ай бұрын
@@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 11 ай бұрын
@@git-amend Also you mention a SceneLoader video but I cannot seem to find it?
@git-amend
@git-amend 11 ай бұрын
@@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 11 ай бұрын
​@@ekekw930 Sry.. brain not working - I meant Service Locator - kzbin.info/www/bejne/emXVZnivjraprbs
@查理-k5s
@查理-k5s 8 ай бұрын
Thanks for this tutorial, but don't compress it to too short, slow down so we won't need to pasued often.
@LuRybz
@LuRybz 11 ай бұрын
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 11 ай бұрын
Thanks for your comments, your feedback is always welcome.
@muhammadzubairirshad6724
@muhammadzubairirshad6724 11 ай бұрын
Just Amazing
@git-amend
@git-amend 11 ай бұрын
Thank you!
@oswaldcobblepot764
@oswaldcobblepot764 11 ай бұрын
I wish i had this 5 years ago :D
@git-amend
@git-amend 11 ай бұрын
I know that feeling!
@lukass1604
@lukass1604 11 ай бұрын
Keep up the videos👍
@git-amend
@git-amend 11 ай бұрын
Will do!
@Andrew-pd2ci
@Andrew-pd2ci 11 ай бұрын
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 KZbin, thank you for the high-quality content
@git-amend
@git-amend 11 ай бұрын
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 11 ай бұрын
@@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 11 ай бұрын
@@Andrew-pd2ci Settings prevent DMs until you get a follow back. Try again.
@laserbean00001
@laserbean00001 11 ай бұрын
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 11 ай бұрын
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 11 ай бұрын
@@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.)
@retrospective9425
@retrospective9425 11 ай бұрын
Hi there....is there any email from you? Any way to make any contact?
@git-amend
@git-amend 11 ай бұрын
You can DM me on Twitter, link is in the description.
@jacobs.7925
@jacobs.7925 11 ай бұрын
Any specific reason to call singleton's namespace Malevolent? 😂😅
@git-amend
@git-amend 11 ай бұрын
Top secret! lol
@xopabyteh
@xopabyteh 11 ай бұрын
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 11 ай бұрын
I agree, it's good to understand and suitable for some projects, but overkill for some.
@nasterofpuppets
@nasterofpuppets 11 ай бұрын
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 11 ай бұрын
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 11 ай бұрын
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 11 ай бұрын
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 11 ай бұрын
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.
@rechnight
@rechnight 5 ай бұрын
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 5 ай бұрын
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 5 ай бұрын
@@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?
@nuin9937
@nuin9937 11 ай бұрын
Way too fast my brain is imploding
@git-amend
@git-amend 11 ай бұрын
You got this!
@-Engineering01-
@-Engineering01- 5 ай бұрын
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 5 ай бұрын
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- 5 ай бұрын
@@git-amend I bought it immediately thank you !
Serialize Types in the Unity Editor using Reflection
11:50
git-amend
Рет қаралды 7 М.
D in SOLID - I wish I learned the LAST letter FIRST
18:00
git-amend
Рет қаралды 8 М.
Noodles Eating Challenge, So Magical! So Much Fun#Funnyfamily #Partygames #Funny
00:33
How To Choose Mac N Cheese Date Night.. 🧀
00:58
Jojo Sim
Рет қаралды 95 МЛН
This Game Is Wild...
00:19
MrBeast
Рет қаралды 181 МЛН
Service Locator: Inversion of Control in Unity C#
19:04
git-amend
Рет қаралды 12 М.
When to use Factory and Abstract Factory Programming Patterns
12:13
SIMPLE Tip For Better Unity Game Architecture
12:57
git-amend
Рет қаралды 37 М.
EASY Stats and Modifiers in Unity | Broker Chain Pattern
16:05
Code Like a Pro: Refactoring to Patterns!
25:52
git-amend
Рет қаралды 6 М.
Unleashing the Power of Event Channels in Unity
21:24
git-amend
Рет қаралды 12 М.
C# Events & Delegates
17:21
Tarodev
Рет қаралды 90 М.
How to Implement Blackboard Architecture in Unity C#
28:57
git-amend
Рет қаралды 14 М.
Abstraction Can Make Your Code Worse
5:13
CodeAesthetic
Рет қаралды 669 М.
Noodles Eating Challenge, So Magical! So Much Fun#Funnyfamily #Partygames #Funny
00:33