When to use Factory and Abstract Factory Programming Patterns

Sdílet
Vložit
  • čas přidán 22. 08. 2024

Komentáře • 66

  • @git-amend
    @git-amend  Před 11 měsíci +13

    24 hour challenge! See if you can find a spot in your current project where you can refactor a section of code to a Factory pattern!
    Hit the bell to keep up with new videos!

    • @stevehamilton321
      @stevehamilton321 Před 9 měsíci +1

      I struggled to find a spot where I couldn't : )

  • @Lago06
    @Lago06 Před 11 měsíci +5

    Thank you so much for sharing your knowledge and covering these advanced topics of game architecture and clean code! In terms of game development there are not much videos out there that target more experienced game developers (I guess mainly because the audience is much smaller). Please don't stop making them, they are very much needed and appreciated!

  • @SnowyLeopardFrom1997
    @SnowyLeopardFrom1997 Před měsícem +1

    I never heard of this concept until 5 minutes ago. I'll need to re-watch this video

    • @git-amend
      @git-amend  Před měsícem

      Sounds good, thanks for watching!

  • @Aliberation
    @Aliberation Před 11 měsíci +2

    Awesome! Thank you for this lecture. For a Game Designer trying to get deeper into code like me, this is treasure. ❤

    • @git-amend
      @git-amend  Před 11 měsíci +1

      Great to hear! More on the way!

  • @Broudy001
    @Broudy001 Před 11 měsíci +2

    Another amazing video, I need to think about how I apply these to my game

    • @git-amend
      @git-amend  Před 11 měsíci

      Awesome! I'm sure you'll find a place for a factory!

  • @castlecodersltd
    @castlecodersltd Před 17 dny

    This was very helpful, thank you 🙂

  • @gabrijel9129
    @gabrijel9129 Před 9 měsíci

    Thank you a whole lot for covering these high level patterns and situations!

  • @derboss66
    @derboss66 Před 10 měsíci

    Thank you very much for creating this video. After watching it, I tidied up a portion of my project :)

  • @dustintaub
    @dustintaub Před 11 měsíci +1

    These are such great, advanced topics.

    • @git-amend
      @git-amend  Před 11 měsíci

      Thanks! Glad you are getting a lot out of the videos!

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

    mate, epic video. I created a whole status effect system using this method by just passing in the equipped weapon into the Create method to define which status to use. very cool and modular and extensible!

    • @git-amend
      @git-amend  Před 7 měsíci +1

      Right on, that's what I like to hear!

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

      Hi mate, One thing i did run into implementing this method (i'm still fairly beginner), is that interfaces and scriptable objects cannot implement monobehaviour. Which also means no Coroutines. I managed to find a workaround by creating a static class which you can pass a coroutine onto and it creates a single empty object to instantiate it. I was just wondering if there was any other strategies to implement monobehaviour using an abstract method like this pattern? My use example was trying to implement a burn over time with 'ticks' over the duration?
      Otherwise would a concrete abstract class that inherits scriptable objects as triggers for the effects be a better solution?
      Love your content mate, still getting across it but its the best videos of design patterns with actual unity examples i've come across! keep doing your thing.

    • @git-amend
      @git-amend  Před 7 měsíci +1

      @@TheFlintMontana For me personally, I tend to roll my own timers. You'll see that in other videos, but you can also see the code here: github.com/adammyhre/3D-Platformer/blob/master/Assets/_Project/Scripts/Utils/Timer.cs
      Alternatively, there is a very good free asset you can use for Coroutines that gives you a lot more control and does not require monobehaviours: assetstore.unity.com/packages/tools/animation/more-effective-coroutines-free-54975

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

      amazing. Thanks mate, i'll get across it today. legend.@@git-amend

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

      One last question, Can you please point me in the direction of where to get Copilot integrated for unity like you have it? Cheers.@@git-amend

  • @hoaxygen
    @hoaxygen Před 11 měsíci +1

    Excellent series

  • @pimor2315
    @pimor2315 Před 9 měsíci +2

    Thank you for the video. I really like factory pattern. I just wonder, in the first example, you are creating factory for each weapon, like SwordFactory and BowFactory and assign one to the Soldier/Knight. Why can't we just have sword and bow as a scriptable objects and assign them directly to the knight? I find it hard to see the benefits of the factory here.

    • @git-amend
      @git-amend  Před 9 měsíci +3

      Thank you for your insightful question. While it's possible to have Sword and Bow as Scriptable Objects and assign them directly, the Factory pattern introduces a layer of abstraction that allows for more complex creation logic that can be easily modified or extended - for instance, if creating a weapon involves setting up multiple parameters or state, a factory can handle this complexity in one place and you won't need a different Scriptable Object for every type of Sword or Bow in your game. In the example in the video, the Sword and Bow are very simple, but you might want your Weapon Factory to have a reference to a secondary Factory which produces a Strategy for calculating damage or for targeting. And if the Factory becomes fairly complex, I would add an internal Builder to it as well.

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

    this was sooo helpful jesus

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

    Thanks, Love it!

  • @TheKr0ckeR
    @TheKr0ckeR Před 9 měsíci +1

    Thanks for the great tutorial! I am always interested in "Architecture" part instead of coding after all these years in Unity and your videos are great source. Thanks for mentioning about more advanced stuffs.
    Do you prefer mono-behaviours more or focusing more on c# plain classes? For example, sword and bow are objects, and probably wont need to be a monobehaviour, but they will have mesh & etc. So do you agree with less mono-behaviour (humble-object pattern - POCO), better code or you just dont worry about it? Another example is health class, health doesnt need to be a mono behaviour since its only doing is decreasing some values etc. But when we need a healthbar, we need to create a monobehaviour to reference Image, fill amount etc. So healthbar will need Health reference to set its current / initial value etc. In tutorials, they both create health.cs and healthbar.cs as monobehaviours and healthbar references the health and subscribes events. But nowadays, Ive started to create healthbar.cs monobehaviour only, and i reference the healthbar in player, enemy etc and create health object inside player, enemy or whatever it is, and initialize healthbar.Init(health) like this. What would you have done situations like this?
    And for the next video suggestion, I would love to see how you seperate UI & Gameplay logic. For example, if we have a ShopUI.cs and buy button in it, would you do the logic inside ShopUI to buy a soldier from a SHOP? We first need to check if we can afford it, then we go soldiermanager and spawn the soldier, inside the ShopUI, or how would you approach this?

    • @git-amend
      @git-amend  Před 9 měsíci +2

      Personally I tend to use C# objects as much as possible, however MonoBehaviours make life easier when you want to hook into the Unity lifecycle. Maybe I can talk about that more in the future. A few people have made similar requests to your video suggestion, so there will be a future video about that too. Cheers!

  • @anasmostefaoui3027
    @anasmostefaoui3027 Před 11 měsíci +1

    I wanted to thank you for the amazing videos, it helped me drastically in my recent project.
    Do you have a Patreon account?

    • @git-amend
      @git-amend  Před 11 měsíci +1

      That is unexpected and very gracious - but I do not actually have anything like that yet. I'm happy to hear my videos helped you out, and I'm curious about your project. Once the channel is a little bit bigger, I have some ideas for some extra resources / rewards that might be of interest to people who want access to those kinds of things through something like Patreon, or maybe even a full course on these kinds of topics.

    • @anasmostefaoui3027
      @anasmostefaoui3027 Před 11 měsíci +1

      @@git-amend I will be the first one to buy your full course, or support you on Patreon. My project is a university final project and your video helped me immensely advancing into building my shoot em' up. What I liked the most is how you apply the design patterns in game development, I usually use them in other software development area, seeing how you were able to implement them and get great value from it in game development was very nice to see and really exciting for me.
      Again, I'm very grateful for your work, I hope to see this channel grow and that your content get the audience it deserves.

    • @git-amend
      @git-amend  Před 11 měsíci +1

      @@anasmostefaoui3027 Thanks for the kind words, and congrats on your final project. I'm very happy to hear that; it's very motivating to hear that a subscriber has benefited from the channel! I will certainly keep you posted on future developments!

  • @rStarStudio
    @rStarStudio Před 11 měsíci +1

    nice video!

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

    As I mentioned before, I generally love using C# regular classes like you do. You have created bow, sword etc. as a plain c# class. But how would you handle what "visual" item to activate when you created Sword, or Bow. For example when we you create BOW, our character should equip the bow. So where do you handle that logic or do you give the item as direct reference to the bow class? I hope i am clear what i am asking. This is a question for how to connect visual elements with pure c# classes, and that is a great example to ask that question. How should player know we equipped the bow and it will activate the required item's etc. I generally have this difficulty when i create factories as plain class and it doesnt know what to activate, ending up complexing stuffs and corrupt the code.

    • @git-amend
      @git-amend  Před 7 měsíci +2

      Well, that's more than I can answer in a comment, but will be a topic of a future video.

  • @laserbean00001
    @laserbean00001 Před 9 měsíci

    Love your anime art clickbaits

  • @shun6284
    @shun6284 Před 6 měsíci +1

    But in real project would you still use factory instead of creating the weapons or shield directly using scriptable and just assign it to the player? Like example for an item you create a Potion Scriptable Object with base class Item that has serialized properties to be customizable and just assign it to player.

    • @git-amend
      @git-amend  Před 6 měsíci +2

      In a simple game assigning a Scriptable Object directly to the player is often sufficient. However, in a more complicated game you would begin to use development principles such as separation of concerns, dependency inversion and abstraction. Assigning items directly to the Player tightly couples the Player to the base class of the item, and the more tightly coupled your game is, the harder it is to make changes in the future. We'll be talking about Inventory systems in some upcoming videos.

  • @thebulletkin8393
    @thebulletkin8393 Před 5 měsíci

    A very clear explanation, but I’m not sure on where this will actually be used. Putting a sword on a knight feels like something you could just assign in the editor beforehand. So would something like this just be used so that say you have a larger army in this rts style game, would it then be used to populate them with weapons at runtime?

    • @git-amend
      @git-amend  Před 5 měsíci

      As your projects grow in complexity, you'll start wanting both to work from abstractions and also move more and more away from MonoBehaviour. The factory gives you the power to supply any interface, or multiple interfaces without tighlty coupling a Sword to your Player. Instead the factory determines what IWeapon to supply at run time, and that could be for all entities in your game. I forget the exact example I used, but the purpose is to decouple your game objects. If your Player just has a [SerializeField] Sword, they can only ever have a Sword. Try to see beyond the 'Weapon' example too though. You might have an ISaveSystem and a SaveSystemFactory that supplies a Json save module, but later you decide to change to Unity cloud save. You only have to change what the Factory supplies and not every single class that needs access to the save system.

  • @zerothehero.takeasip6612
    @zerothehero.takeasip6612 Před 10 měsíci

    Niiice video! Gamedev youtube rarely goes beyond the novice level so it´s nice to see design patterns applied to Unity! Question about the abstract factory though. If you have an abstract factory, which from what I understand is just having a bunch of factories grouped in one place, then what is the point of having made those individual factories to begin with? Why not just make each of the create methods within the equipment factory and you save yourself from having to add references to the original factories? It was hard to see the use from your example. I think it would be good if you could show a 2nd more complex example for each of these design patterns to see their benefit more clearly. So many programming conventions seem useless at the simple level as simpler techniques would suffice and it isn´t until you expand that you realize their use. Hence, I don´t think there is anything with how you taught it but I was left a bit unsure of the benefits of the abstract factory with the example provided.

    • @git-amend
      @git-amend  Před 10 měsíci +1

      Great to hear that you found the video helpful and are interested in diving deeper! You're right; design patterns like the Abstract Factory often show their true colors when the complexity of the system increases. To address your question: The value in having separate factories and then grouping them into an abstract factory lies in modularity, separation of concerns, and ease of extension. By keeping individual factories, you can specialize them for creating particular types of objects, which may involve complex instantiation logic that is best kept isolated. An Abstract Factory serves as an orchestrator that can produce a family of related objects by composing these specialized factories.
      In a game development context, imagine you're making a multi-theme game with "Forest" and "Desert" environments. Each environment has its own types of enemies, plants, and weather conditions. By having individual factories for each category (EnemyFactory, PlantFactory, WeatherFactory), and then using a "ForestAbstractFactory" or "DesertAbstractFactory" to group them, you can easily switch between environments by simply switching the abstract factory. Each specific factory already knows how to create enemies, plants, etc., specific to its environment. So, when you decide to add a new theme like "Ocean", you can easily extend the system by creating new individual factories and a new abstract factory without touching the existing code. This makes your code more maintainable and scalable.

    • @zerothehero.takeasip6612
      @zerothehero.takeasip6612 Před 10 měsíci

      ​@@git-amend I think I understand now, thank you! Though following up on your example, would it be recommendable to have the abstractEnvironmentFactories (forest, desert, and ocean) all inheret from one class that has all the factories or would you recommend another approach. I ask, cause I was curious about the organization of the elements within the factories and I know having too many inheretances can get messy quickly. Thoughts?

    • @git-amend
      @git-amend  Před 10 měsíci +1

      @@zerothehero.takeasip6612 Great follow-up question! Like all engineering decisions, the answer is always, 'it depends!' Generally speaking, I would start with a base interface that your consumer class can use. For example, IEnvironmentStrategy could define methods for CreateEnemy, CreatePlant, and CreateWeather. This keeps things simple and doesn't add unnecessary layers of inheritance.
      If there are common behaviours or shared resources among all the environment factories, then having an additional base abstract class might make sense. The base class could implement some common logic and hold references to shared resources, even concrete sub-factories, if used by all types of environment factories. However, this approach does introduce an additional layer in your inheritance hierarchy, which, as you mentioned, could get messy if not managed carefully. I tend to only include an abstract base class if there are some common variables or resources needed by all concrete implementations of the interface - I start with the simplest way possible and only refactor to a higher level of complexity when the need arises. Often, you will find that once the concrete versions of your factory start to take shape, you'll find enough common elements to warrant a shared abstract class, at which point the refactoring is clear and easy to do.

    • @zerothehero.takeasip6612
      @zerothehero.takeasip6612 Před 10 měsíci

      @@git-amend Thank you for the great reply, I am still trying to habitually implement these patterns into my coding. Keep up the good work!

  • @Forture-fm1ve
    @Forture-fm1ve Před 8 měsíci

    Thank you for your video. In your first example, can I create an abstract class 'WeaponBase' to encapsulate all common attributes and then use interfaces as you did to create different types of weapons?

    • @git-amend
      @git-amend  Před 8 měsíci +1

      Absolutely. My general practice is to start with an interface, create 2-3 concrete types and at that point determine if it's worth extracting common elements into an abstract base class. Cheers!

    • @Forture-fm1ve
      @Forture-fm1ve Před 8 měsíci

      You're welcome for your answer.@@git-amend

  • @yeric17
    @yeric17 Před 8 měsíci

    ¡Gracias!

    • @git-amend
      @git-amend  Před 8 měsíci

      Wow thank you!

    • @yeric17
      @yeric17 Před 8 měsíci

      @@git-amend Your content is of great quality, your videos are impressive.

  • @umoyGC
    @umoyGC Před 9 měsíci

    Hi Adam, I wonder if there is a possiblity in using this factory pattern for switching skinned mesh renderer "objects".
    I wanted to change Armor parts of a sinty studios model. my code is working so far but it is a giant mess of swich cases if the part is an arm or the helmet and so on. What do you think can be a good approach to that? Also using interfaces for the body parts or have you a better or "smoother" idea :)
    Thanks in advance for reading my comment :)

    • @git-amend
      @git-amend  Před 9 měsíci +3

      Great comment, and perhaps a great topic for a future video, as I know this is a pain point for many people. While the Factory pattern is useful for creating objects, a more suitable pattern for this scenario could be the Strategy pattern. Here's a brief overview:
      The Strategy pattern is used to define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from objects that use it. In this context, each type of armor part (helmet, arm, etc.) could be treated as a strategy. You can create an interface, say IArmorPart, with a method like ApplyPart() or ChangePart(). Then, implement this interface in different classes representing different armor parts.
      This approach will remove the need for switch cases and will make the code more organized. Each armor part's behaviour is encapsulated in its respective class.
      You could still use a Factory to create your various Weapons and Armor, but when creating them, you also provide each with an appropriate Strategy that will contain the logic for applying themselves to your character(s). Small example:
      public interface IArmorPart {
      void ApplyPart(GameObject character);
      }
      public class PlayerEquipment : MonoBehaviour {
      public IArmorPart currentArmorPart;
      // or maybe Dictionary equipment;
      public void ChangeArmorPart(IArmorPart newArmorPart) {
      currentArmorPart = newArmorPart;
      currentArmorPart.ApplyPart(gameObject);
      }
      }
      [CreateAssetMenu(...)]
      public class HelmetPlacementStrategy : ScriptableObject, IArmorPart {
      public Mesh helmetMesh;
      public Material helmetMaterial;
      public void ApplyPart(GameObject character) {
      // Logic to actually change the armor on the character.
      // For example, find the helmet mesh renderer and apply the new mesh and material,
      // or activate/deactivate GameObjects.
      }
      }
      This way your various strategies determine what happens when you 'Apply' them to your character, and not a huge list of conditional statements. Hope that helps give you some ideas!

    • @umoyGC
      @umoyGC Před 9 měsíci +1

      Many thx for this amazing fast and detailed answer. I will track the video about strategy patterns and will try my best to update my code in a clean and efficient way. Thank you so much :) @@git-amend

  • @castlecodersltd
    @castlecodersltd Před 16 dny

    I built a factory for NetworkBehaviour class that had a Builder which was working great until I tried it with more than just the host running:
    "[Netcode] Failed to create object locally. [globalObjectIdHash=0]. NetworkPrefab could not be found. Is the prefab registered with NetworkManager?"
    I was trying not to use prefabs, in my factory with Builders, but I'm guessing it's the only way to go for NetworkObjects or am I missing something (chances are high)? Or is it a case to just use a very basic GameObject with a NetworkObject attached (and registered as a prefab) and then add Components when building the object?
    Hopefully I've explained that correctly 🙂

    • @git-amend
      @git-amend  Před 16 dny +1

      With Unity's NGO, each NetworkObject must be associated with a registered prefab in the NetworkManager. This ensures that all clients in a multiplayer session can instantiate the same object consistently. When you encounter the error "[Netcode] Failed to create object locally," it typically indicates that the object you are trying to create has not been registered as a prefab in the NetworkManager.
      To solve this while still using a factory pattern, you can register a basic prefab containing a NetworkObject with the NetworkManager and then use your factory to add additional components or customize the object after instantiation. This approach allows you to maintain the flexibility of the builder pattern while satisfying the network system's requirements for synchronization across clients.

    • @castlecodersltd
      @castlecodersltd Před 16 dny

      @@git-amend thank you, that's what I ended up going with. All the best 🙂