Unity3D SOLID Principles - Dependency Inversion Principle

Sdílet
Vložit
  • čas přidán 29. 08. 2024
  • Check out the Course: bit.ly/3i7lLtH
    -------
    See how to apply the Dependency Inversion principle to your projects (without using a DI container or framework). We'll go over a few samples and show yor you can split up your code, pass in dependencies, and have code that doesn't quickly become spaghetti :)
    More Info: unity3d.college
    Join the FB Group: unity3d.group

Komentáře • 92

  • @onurtnrkl
    @onurtnrkl Před 6 lety +153

    Great example, no one talks about solid principles or design patterns in unity. I follow you for a long time, you deserve much more subscribers.

    • @lukasvasek9658
      @lukasvasek9658 Před 6 lety

      Are you sharing every video ? If you dont, dont talk about he deserve a shit

    • @onurtnrkl
      @onurtnrkl Před 6 lety +12

      Lukáš Vašek I don't use social media. Yes, I share videos but only with my friends.

    • @aaronpaulina
      @aaronpaulina Před 6 lety +11

      clearly a crazy person^

    • @118andrey
      @118andrey Před rokem

      Unfortunately you find out about the only in job interviews when it's too late

    • @starbuck3980
      @starbuck3980 Před 3 měsíci

      @@118andrey its just useful for job interviews

  • @christobanistan8887
    @christobanistan8887 Před 5 lety +26

    It's not "dependency injection" if you're deciding which implementation to use in Awake(). But I don't think DI is easy to fit into MonoBehaviors and shouldn't be shoe horned in, so I think you did very a great job just separating concerns using interfaces and SOs.
    But DI is easy and very useful outside MonoBehaviors as part of a larger set of infrastructure classes!
    Great video, man. This series is really helping me learn Unity.

    • @darsheelrathore3069
      @darsheelrathore3069 Před 4 lety

      Sir can i use zenject framework for DI in unity... Or something else will be more beneficial or just manual IOC, pls give a light on it.
      Thanks in advance... ❤️

    • @DoomCatcher
      @DoomCatcher Před 2 lety

      How would you recommend applying depency inversion in unity now?

  • @LuRybz
    @LuRybz Před 6 lety +18

    Unity3D College is a hidden and precious gem.
    Thank you for sharing your knowledge and experience!

  • @shadesbelow
    @shadesbelow Před 6 lety +6

    Holy shit, this guy is good. More Unity devs should know about this channel. Let's spread the word!

  • @Ne0mega
    @Ne0mega Před 6 lety +5

    Every Second of these SOLID videos are worth their weight in solid gold. I know it was impossible for time to have weight, but that changed when these videos were posted.

  • @marekrutkowski3028
    @marekrutkowski3028 Před rokem

    Dependency Injection is NOT Inversion of Control. For IoC this is a very Well done tutorial. For DI (Dependency Injection) just use Zenject / Extenject project.

  • @lorenfulghum2393
    @lorenfulghum2393 Před 4 lety +3

    You're the best unity teacher i've ever seen. So clear.

  • @Pookzob
    @Pookzob Před 6 lety +6

    Short, condensed, and just crammed with _great_ information about lots of good practices.
    This made the coin drop for me with scriptable objects. Didn't feel like I got it quite right before when trying to use them but now I'm all set to do it properly!
    Keep up the amazing work!

    • @MMMM-vc5oi
      @MMMM-vc5oi Před 6 lety

      He has put aside components in unity!! Is it fantastic?! Absolutely no. If you want to access ShipInput or ShipMotor outside of the Ship script, what do you do? You need GetComponent instead of GetComponent for example!

  • @michaelday5605
    @michaelday5605 Před 5 lety +3

    thank you so much for making these videos. I made a few games by watching unity tutorials and I'm trying to extend them into something that I can actually release and would be fun to play. I'm running into some limitations of the way the tutorials designed a lot of the objects in relationships and your videos are giving me some fantastic ideas on how to rewrite the code using solid design principles.

  • @UmarFarooq-jn7dt
    @UmarFarooq-jn7dt Před 2 lety

    YOU are a Legend! Watched a lot of videos to grasp SOLID. But, your example of Liskov Substitution was the best one. Big Thanks!

  • @behnamrasooli8801
    @behnamrasooli8801 Před 6 lety +52

    Please be aware that Dependency Inversion and Dependency Injection are not the same thing. In this tutorial you're talking about Dependency Injection. Dependency Inversion is when a high level class is depending on the abstraction of a low level class rather than depending on that low level class itself. Dependency Injection on the other hand is when a class is injected with whatever object it needs to operate on, so it doesn't need to instantiate that object within itself .

    • @christobanistan8887
      @christobanistan8887 Před 5 lety +5

      Either way, this is neither DI. This is just SOC based on settings and interfaces, which is good too.

    • @soonfamous
      @soonfamous Před 4 lety +1

      @@christobanistan8887 What does SOC stands for?

    • @davidbonnefond8546
      @davidbonnefond8546 Před 4 lety +3

      @@soonfamous SoC - separation of concern

  • @VaporTrap
    @VaporTrap Před 5 lety

    Thanks for the vids guy, most tutorials tell you how to do something but you tell us why to do it. Much more beneficial to an intermediate noob like me who understands basic methods, syntax, variables, etc. but is expanding my small project and quickly getting lost in my mess of code.

  • @JalerSekarMaji
    @JalerSekarMaji Před rokem

    Thank you very much Jason, for providing SOLID that has really SOLID EXAMPLE as well!
    May the force be with you!

  • @kimeiga
    @kimeiga Před 6 lety

    Frankly I don't exactly know just yet how I will apply this principle to my current projects, but I can definitely see the benefits of all this separation!

  • @farhatfazeli
    @farhatfazeli Před 7 měsíci

    Thank you for your clean and useful example

  • @moodyfilms4
    @moodyfilms4 Před 3 lety

    Great video! Came here after five other videos on DIP and this is the one that made it click for me!

  • @carlomontoya
    @carlomontoya Před 4 lety

    Thank you for the complete and concise explanation of this principle.

  • @shermenz
    @shermenz Před 6 lety +1

    I just found this channel.
    Solid work sir, thank you so much.

  • @arthurbourdot8765
    @arthurbourdot8765 Před 3 lety

    Hello Jason, thank you a lot, your courses are helping a lot to understand the logic behind making video-games !

  • @stropheum
    @stropheum Před 2 lety

    [RequireComponemt] is a great way to enforce dependency binding at compile time as well!

  • @soyfandev4925
    @soyfandev4925 Před 4 lety

    thank u so much jason, please share the video on social media platform he deserve a lot

  • @videoaulasmayleone
    @videoaulasmayleone Před 3 lety

    Amazing example! We always heard about dependency injections and IoC, but I've never seen before these patterns being explained using Unity.
    The implementation in Unity is a little different (and maybe controversial), but the principle is the same independent of framework.
    But I want to comment about Ship class: Instead passing these information on ShipMotor constructor, I'd create a struct who handle it, and would pass the instance as param, something like this:
    public struct ShipDependences{
    public ShipSetting shipSettings;
    public IShipInput shipInput;
    public Transform transformToMove;
    }
    Ship class:
    private ShipDependences shipDep;
    private void Awake(){
    shipDep = new shipDependences();
    shipDep.shipSettings = this.shipSettings;
    shipDep.shipInput = // The same code from video
    shipDep.transformToMove = this.transform;
    shipMotor = new ShipMotor(shipDep);
    }

  • @tlucz7572
    @tlucz7572 Před 6 lety +1

    Thanks for all your tutorials. They are really helpful. Could you cover the unit (or even integration) testing in unity in the future videos? It would be very interesting and consistent with SOLID principles.

  • @Ferenc-Racz
    @Ferenc-Racz Před 3 lety

    Nice work! Composition over inheritance is the best thing in OOP :)

  • @eyli
    @eyli Před 4 lety

    Wow, gave me a new perspective on everything - really wish I found this sooner.
    Thank you for the great video and explanation.

  • @FacePalmProduxtnsFPP
    @FacePalmProduxtnsFPP Před 6 lety +1

    Good vocal balancing man! Great tutorials!

  • @ruhanbello3983
    @ruhanbello3983 Před 5 lety +1

    The D on SOLID is not about Dependency Injection, it is about Dependency Inversion. But I liked your explanation about Dependency Injection!

  • @fokeyjo
    @fokeyjo Před rokem

    Unity is one big dependency injection engine, isn't it? That's the whole point of the properties - unity is the service object layer defining the makeup of dependency injections into the monobehaviours, and the monobehaviours being equally injections into the components being placed in the hierarchy.
    From looking at a few other descriptions on dependency inversion, it's essentially the idea that intercommunicating classes have interfaces that they communicate through, so that you are never relying on concrete implementations directly, such that you can change out the concrete implementation class. So actually your substitution video was probably closer to it where your attackMelee function used two interfaces of intercommunicating classes to perform a complementary task with them. Maybe adapter pattern is the easiest explanation!
    Also, the third example broke another handy facility which is being able to dynamically unload the AI while the game is running.

  • @karolsobanski8913
    @karolsobanski8913 Před 6 lety +3

    Thx you, this tutorial was really helpful for me. Can you do more Profesional tutorials like this ? I mean using patterns and good programic convension in Unity ;).

  • @jeanmestti6195
    @jeanmestti6195 Před rokem +1

    What if we directly used a version of Tick ( ) with parameters instead of cache variables ?, something like Tick ( IInput, Tranform, Shipsetings ) that apparently would have the same effect without having to instantiate the object on Ship class.

  • @CAmygdala
    @CAmygdala Před 6 lety +1

    Thank you for these videos. I'm a huge advocate for clean, testable code and these videos are exactly what I've been looking for as I develop projects in Unity.
    I have a quick question: is there a strong reason you chose to implement IShipInput as an interface and not a base class? It seems to me like using a base class would make more sense in this example since the functionalities of "ship input" would be specific to the ship.

  • @rafa_guitar
    @rafa_guitar Před 6 lety

    Thank you very much for your very useful and awesome videos!

  • @MultiDevan13
    @MultiDevan13 Před 4 lety

    As Game Dev and Design student, they should be teaching stuff like this...

  • @HowToMakeMobileGames
    @HowToMakeMobileGames Před 6 lety

    great series of videos.

  • @touristtam
    @touristtam Před 5 lety +4

    SOLID explanation :)

  • @zekiozdemir420
    @zekiozdemir420 Před 2 lety

    thank you!

  • @Kramlets
    @Kramlets Před 6 lety +3

    Please could you provide the project in the description? That would be really helpful for me to pick apart.

    • @Unity3dCollege
      @Unity3dCollege  Před 6 lety +9

      Here ya go - unity3dcollege.blob.core.windows.net/site/YTDownloads/Dependency%20Inversion.zip

  • @nipunasudha
    @nipunasudha Před 6 lety +1

    Thank you very very much man

  • @MQNGameDev
    @MQNGameDev Před 5 lety

    Awesome, thanks for the great info.

  • @kepazino
    @kepazino Před 3 lety

    Second one seems easy enough, third one is mad!

  • @alexanderzotovthe2nd230
    @alexanderzotovthe2nd230 Před 6 lety +4

    You are digging so deep. You are really have kind of missing manual channel) So you are from NASA) That explains a lot)

  • @Balakademi
    @Balakademi Před 2 lety

    Thanks

  • @risingforce9648
    @risingforce9648 Před 4 měsíci

    Hey jason that implementation is similar to Proxy Pattern right? or I am wrong.... I mean Unity has differnte approach in IOC , less generic thatn the IoC ...and Factory method is DI ... so if Ioc is more generic implementaion of DI:.. Unity provides by Awake a fake constructor? so it is a Lightway Ioc?

  • @willsaymon
    @willsaymon Před 5 lety

    Awesome channel! :)

  • @Glubina13100Guitar
    @Glubina13100Guitar Před 6 lety +1

    Hi Jason, thanks for the video! I am in search of good ways to implement DI principle in my projects and have read some articles explaining how people do this. And I also made a research of main defference between interface and abstract classes, which seems to boil down to the rule: abstract classes are used to unify related classes while interfaces do the same but for separate classes.
    I was always interested what is the profit of using interfaces compared to abstract classes in order to follow DI principle?
    In your video we see that you made an abstraction on ShipInput, which is great, but why you didn't use an abstract class like AShipInput with ControllerInput and AIInput as its children?
    This seems to make sence because both ConreollerInput and AIInput represent the same purpose - working with input. From my perspective it is worth to gather such classes under parent abstract class, not interface.
    The same question comes from the code review you've made recently czcams.com/video/djLU7_SVZ8U/video.html#t=6m. There's also an abstraction of input and it was implemented using interfaces, while I would go for an abstract class.
    What am I missing? Could you please elaborate the choice of using the interface approach?

    • @aronlinde1723
      @aronlinde1723 Před 5 lety +1

      Interfaces share Behaviors. Classes (objects) share function and structure.
      A better way to think about interfaces is that they provide a signature of behaviors, but provide no promise of function/structure. This provides a high level of abstraction and decouples the two regions of code.
      This is why I am not a fan of abstract methods. They split the difference on interfaces and strong classes creating a very weak class that doesnt promise function nor provides reliable abstraction.

  • @alicem3415
    @alicem3415 Před 2 lety

    I'm trying to apply these principles, but sometimes it just feels silly. Like I've vastly expanded the number of classes I have and it would seem far more difficult now to show someone my scripts and have them understand it. And for what? So if I decide to add some feature later it might be easier? Wouldn't planning be more effective?
    Is there a justifiable reason to apply this principle to a small solo project? I'm trying to, but I just feel like a clown adding all these interfaces and new classes to create what was previously a pretty simple single Monobehaviour, though one that violated SOLID principles.

  • @BlackvZ23
    @BlackvZ23 Před 6 lety

    Thanks for the idea. :)

  • @halivudestevez2
    @halivudestevez2 Před 3 lety

    Interface ! yess! :)

  • @trstensvold
    @trstensvold Před rokem

    I have heard that Dependency Injection is Dependency Inversion, but Dependency Inversion is not necessarily Dependency Injection.

  • @BlueBirdgg
    @BlueBirdgg Před 4 lety

    Oh well, I dont know if you know this, but I think I've read on some efficiency Manuals on Unity that the "? :" operators is inefficient.

  • @DoomCatcher
    @DoomCatcher Před 2 lety

    This is really helpful but It would be much easier to follow if you offered the project/source code for download

  • @hojaverde5265
    @hojaverde5265 Před 6 lety

    Excelent video and example, thank you again. Would you upload the code?

  • @sohamjoshi9527
    @sohamjoshi9527 Před 4 lety

    Very helpful ! I have a question. I see that we can do property injection basically using the scriptable object drag drop method. However, what if I property inject via the editor an implementation of (lets say) IDoSomethingService on multiple monobehaviors across multiple scenes. And now I wish to replace it with another concrete implementation across my scenes. I would need to trace manually through every monobehvior that consumes the old implementation and change it. The traditional DI allowed a bootstrapmethod in which I could change one line to hook up the new concrete implementation. This is because in the traditional DI the container acts like a factory which is another layer of abstraction between the concrete implementation instance supplied and the consumer of that instance. In case of using unity editor we lose this abstraction leading to the problem i just mentioned. Do you have a solution for how I could switch out a concrete implementation when using unity editor property injection. Thanks !

  • @ishan9815
    @ishan9815 Před 4 lety

    Is there any way I can download this project!!
    Great Explaination

  • @dmytrosavostianov3055
    @dmytrosavostianov3055 Před 3 lety

    Isn't it an MVC pattern?
    Sorry, might be a stupid question.

  • @emanmomot
    @emanmomot Před 6 lety

    What is the benefit of this? Wouldn't you want to keep your different components as Monobehaviors so that you can interact with them through the inspector?

    • @aronlinde1723
      @aronlinde1723 Před 5 lety

      You can and should keep some things as Monobehavior or as substitute for MB. This is a very good method once you are outside the area of the editor, such as with services (which are really hard to MB out once you pass the base object) or with data created objects such as if you build prefabs on the fly.

    • @christobanistan8887
      @christobanistan8887 Před 5 lety

      With the ScriptableObject you can interact with them through the inspector.

  • @NipunDavid
    @NipunDavid Před 4 lety

    new AiInput() as IShipInput, can you please explain the syntax of this statement?

    • @carlomontoya
      @carlomontoya Před 4 lety

      Jason replied to same question by neevir below. I thought at first it was because ShipMotor constructor was expecting an IShipInput interface so it was casts to that.

  • @Tech_Alchemy
    @Tech_Alchemy Před 6 lety

    Hey Jason, I didn't know you had a channel. :)
    Subd.

  • @neevir3229
    @neevir3229 Před 6 lety +1

    What's the meaning of "as IShipInput" on line 13 at 7:00 ?

    • @LinhNguyen-zt3mg
      @LinhNguyen-zt3mg Před 6 lety

      Casting. Like x =(IShipInput)y. But i think it no need for this case.

    • @Unity3dCollege
      @Unity3dCollege  Před 6 lety +2

      It's just there so the ? operator will work . Without casting it, it doesn't know that we want to use it as an IShipInput so it gives an error because the 2 types that implement it are different. If it weren't for that operator, it wouldn't be needed.

    • @LinhNguyen-zt3mg
      @LinhNguyen-zt3mg Před 6 lety

      yeah, i mistaked.

    • @christobanistan8887
      @christobanistan8887 Před 5 lety

      @@Unity3dCollege Another reason to avoid the ? : operator.

  • @ItsAllGoodGames
    @ItsAllGoodGames Před 6 lety

    interfaces always confuse the shit out of me.
    If i had to do this, id probably create a generic Ship.cs script which has public Move(var thrust, var direction), then id have 2 scripts called PlayerControl.cs and AIControl.cs, and whichever one is added as a component will take control of the ship.
    and if the game is really really simple, id just a have a boolean toggle in the Ship.cs script itself and eat the cost of If statement checking the boolean before movement.
    unless theres a way to put methods inside an array, so i can set a value to 0(player), 1(AI) in Awake() based on inspector toggle, and have an array containing playermove() in index[0], aimove in index[1], and then just call it in update() without if statements.

    • @Unity3dCollege
      @Unity3dCollege  Před 6 lety +3

      It becomes a bit more apparent when you start intermingling systems. Having a system that deals damage to a Ship vs one that takes an ITakeDamage interface can make a big difference. I'll have to do a few more videos on this though to really explain it I think :)

  • @magictimm4090
    @magictimm4090 Před 4 lety

    Jason, thanks for your great videos. I put all your code in my project which is a top down shooter. The movement from the player and the enemy works (nearly) fine but the control of the player is like running on ice. The character is not stopping exactly after key is up. He slides a little bit in the move direction. May be you or someone else can help.
    public class CharacterMovement
    {
    private readonly ICharacterInput characterInput;
    private readonly Transform transformToMove;
    private readonly CharacterSettings characterSettings;
    public CharacterMovement(ICharacterInput characterInput, Transform transformToMove, CharacterSettings characterSettings)
    {
    this.characterInput = characterInput;
    this.transformToMove = transformToMove;
    this.characterSettings = characterSettings;
    }
    public void MoveTick()
    {
    Vector3 movement = new Vector3(characterInput.Horizontal, characterInput.Vertical).normalized;
    transformToMove.position += movement * Time.deltaTime * characterSettings.MoveSpeed;
    }
    }
    public class ControllerInput : ICharacterInput
    {
    public void ReadInput()
    {
    Horizontal = Input.GetAxis("Horizontal");
    Vertical = Input.GetAxis("Vertical");
    }
    public float Horizontal { get; private set; }
    public float Vertical { get; private set; }
    }
    public class Character : MonoBehaviour
    {
    [SerializeField] private CharacterSettings characterSettings;
    private ICharacterInput characterInput;
    private CharacterMovement characterMovement;
    private void Awake()
    {
    characterInput = characterSettings.UseAi ?
    new AiInput() as ICharacterInput :
    //if not
    new ControllerInput();
    characterMovement = new CharacterMovement(characterInput, transform, characterSettings);
    }
    private void Update()
    {
    //Input for movement
    characterInput.ReadInput();
    characterMovement.MoveTick();
    }
    }

  • @starbuck3980
    @starbuck3980 Před 3 měsíci

    Hate solid principles, just make everything more complicated and the game runs just fine without them, just useful to know for interviews

  • @simpson6700
    @simpson6700 Před 4 lety

    this doesn't seem very clean either, sure your code is cleaner, but your dependencies and your editor can quickly become a mess.

  • @MMMM-vc5oi
    @MMMM-vc5oi Před 6 lety +2

    Sorry but it was awful. Unity uses components.You put aside components because of using interfaces!! You should utilize components that implement interfaces. Components are so useful that it is not required to explain but you throw away them.

    • @GuillemPoy
      @GuillemPoy Před 5 lety

      Sorry, but for me, this code increases the maintainability, scalability, update facility, usability, and export capacity of the entire project.

  • @bitmammothOG
    @bitmammothOG Před rokem

    this does great for me until I need complex data storage services, specifically easycaching.hybrid and dapper with redis bus lol