Unity3D SOLID Principles - Dependency Inversion Principle

Поделиться
HTML-код
  • Опубликовано: 3 дек 2024

Комментарии • 92

  • @onurtnrkl
    @onurtnrkl 7 лет назад +155

    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 7 лет назад

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

    • @onurtnrkl
      @onurtnrkl 7 лет назад +12

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

    • @aaronpaulina
      @aaronpaulina 7 лет назад +11

      clearly a crazy person^

    • @118andrey
      @118andrey Год назад

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

    • @starbuck3980
      @starbuck3980 6 месяцев назад

      @@118andrey its just useful for job interviews

  • @LuRybz
    @LuRybz 6 лет назад +18

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

  • @Ne0mega
    @Ne0mega 6 лет назад +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.

  • @christobanistan8887
    @christobanistan8887 5 лет назад +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 4 года назад

      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 3 года назад

      How would you recommend applying depency inversion in unity now?

  • @shadesbelow
    @shadesbelow 6 лет назад +6

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

  • @lorenfulghum2393
    @lorenfulghum2393 5 лет назад +3

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

  • @UmarFarooq-jn7dt
    @UmarFarooq-jn7dt 2 года назад

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

  • @Pookzob
    @Pookzob 7 лет назад +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 6 лет назад

      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 5 лет назад +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.

  • @marekrutkowski3028
    @marekrutkowski3028 2 года назад

    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.

  • @moodyfilms4
    @moodyfilms4 4 года назад

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

  • @VaporTrap
    @VaporTrap 5 лет назад

    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 2 года назад

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

  • @kimeiga
    @kimeiga 7 лет назад

    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!

  • @carlomontoya
    @carlomontoya 4 года назад

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

  • @farhatfazeli
    @farhatfazeli 10 месяцев назад

    Thank you for your clean and useful example

  • @shermenz
    @shermenz 6 лет назад +1

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

  • @soyfandev4925
    @soyfandev4925 5 лет назад

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

  • @arthurbourdot8765
    @arthurbourdot8765 3 года назад

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

  • @FacePalmProduxtnsFPP
    @FacePalmProduxtnsFPP 7 лет назад +1

    Good vocal balancing man! Great tutorials!

  • @videoaulasmayleone
    @videoaulasmayleone 4 года назад

    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);
    }

  • @Ferenc-Racz
    @Ferenc-Racz 3 года назад

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

  • @eyli
    @eyli 4 года назад

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

  • @tlucz7572
    @tlucz7572 7 лет назад +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.

  • @stropheum
    @stropheum 2 года назад

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

  • @behnamrasooli8801
    @behnamrasooli8801 6 лет назад +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 5 лет назад +5

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

    • @soonfamous
      @soonfamous 4 года назад +1

      @@christobanistan8887 What does SOC stands for?

    • @davidbonnefond8546
      @davidbonnefond8546 4 года назад +3

      @@soonfamous SoC - separation of concern

  • @karolsobanski8913
    @karolsobanski8913 6 лет назад +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 ;).

  • @touristtam
    @touristtam 5 лет назад +4

    SOLID explanation :)

  • @ruhanbello3983
    @ruhanbello3983 6 лет назад +1

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

  • @rafa_guitar
    @rafa_guitar 6 лет назад

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

  • @kepazino
    @kepazino 4 года назад

    Second one seems easy enough, third one is mad!

  • @MultiDevan13
    @MultiDevan13 5 лет назад

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

  • @HowToMakeMobileGames
    @HowToMakeMobileGames 6 лет назад

    great series of videos.

  • @jeanmestti6195
    @jeanmestti6195 Год назад +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.

  • @MQNGameDev
    @MQNGameDev 5 лет назад

    Awesome, thanks for the great info.

  • @CAmygdala
    @CAmygdala 6 лет назад +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.

  • @Kramlets
    @Kramlets 7 лет назад +3

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

    • @Unity3dCollege
      @Unity3dCollege  7 лет назад +9

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

  • @nipunasudha
    @nipunasudha 6 лет назад +1

    Thank you very very much man

  • @zekiozdemir420
    @zekiozdemir420 3 года назад

    thank you!

  • @fokeyjo
    @fokeyjo Год назад

    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.

  • @wyrukun
    @wyrukun 5 лет назад

    Awesome channel! :)

  • @halivudestevez2
    @halivudestevez2 3 года назад

    Interface ! yess! :)

  • @ishan9815
    @ishan9815 4 года назад

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

  • @hojaverde5265
    @hojaverde5265 6 лет назад

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

  • @Balakademi
    @Balakademi 2 года назад

    Thanks

  • @BlackvZ23
    @BlackvZ23 6 лет назад

    Thanks for the idea. :)

  • @AstralNostalgia
    @AstralNostalgia 8 месяцев назад

    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?

  • @DoomCatcher
    @DoomCatcher 3 года назад

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

  • @alexanderzotovthe2nd230
    @alexanderzotovthe2nd230 7 лет назад +4

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

  • @sohamjoshi9527
    @sohamjoshi9527 5 лет назад

    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 !

  • @Glubina13100Guitar
    @Glubina13100Guitar 6 лет назад +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 ruclips.net/video/djLU7_SVZ8U/видео.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 5 лет назад +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 2 года назад

    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.

  • @BlueBirdgg
    @BlueBirdgg 5 лет назад

    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.

  • @neevir3229
    @neevir3229 7 лет назад +1

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

    • @LinhNguyen-zt3mg
      @LinhNguyen-zt3mg 7 лет назад

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

    • @Unity3dCollege
      @Unity3dCollege  7 лет назад +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 7 лет назад

      yeah, i mistaked.

    • @christobanistan8887
      @christobanistan8887 5 лет назад

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

  • @Tech_Alchemy
    @Tech_Alchemy 7 лет назад

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

  • @NipunDavid
    @NipunDavid 4 года назад

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

    • @carlomontoya
      @carlomontoya 4 года назад

      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.

  • @emanmomot
    @emanmomot 6 лет назад

    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 5 лет назад

      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 5 лет назад

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

  • @trstensvold
    @trstensvold Год назад

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

  • @dmytrosavostianov3055
    @dmytrosavostianov3055 4 года назад

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

  • @ItsAllGoodGames
    @ItsAllGoodGames 6 лет назад

    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  6 лет назад +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 4 года назад

    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();
    }
    }

  • @simpson6700
    @simpson6700 5 лет назад

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

  • @starbuck3980
    @starbuck3980 6 месяцев назад

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

  • @MMMM-vc5oi
    @MMMM-vc5oi 6 лет назад +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 5 лет назад

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

  • @bitmammothOG
    @bitmammothOG Год назад

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