Better Coding in Unity With Just a Few Lines of Code

แชร์
ฝัง
  • เผยแพร่เมื่อ 21 พ.ย. 2024

ความคิดเห็น • 509

  • @looty20-q8q
    @looty20-q8q 10 หลายเดือนก่อน +8

    I love how slowly you explain stuff. It easy to understand the point :))

  • @Zicore47
    @Zicore47 2 ปีที่แล้ว +173

    State machines are great, but they don't reduce spaghetti code. In all your examples you could invert the ifs and return early to reduce nesting. Also keep in mind that virtual methods can add a performance overhead. Stick to KISS and composition over inheritance. Still a good tutorial for learning the concept.

    • @Konitama
      @Konitama 2 ปีที่แล้ว +8

      Yeah this is called a Guard Clause and I've been using it a lot more in my own code to reduce if conditions

    • @nathanfranck5822
      @nathanfranck5822 ปีที่แล้ว +4

      Yay, now it's spaghetti that's more annoying to trace/read

    • @nathanfranck5822
      @nathanfranck5822 ปีที่แล้ว +1

      People who avoid simple structural coding because "wahh it looks messy" are hilareous. I bet they'd put bags in bins in three layers of boxes when they organize their shelf storage too. Have fun unpacking all that later

    • @K3rhos
      @K3rhos ปีที่แล้ว

      @@nathanfranck5822 It's way better to use inverted if with return, it's way easier to read and also way better when you need to put Debug.Log right before the return; So you can trace where it's passing or not, when with a classic if statement you will need to add a tons of "else" when something goes wrong, a real spaghetti code !

    • @PixelPressChannel
      @PixelPressChannel 8 หลายเดือนก่อน +3

      ​@@nathanfranck5822Nah man, this is WAY easier to trace if there are too many nested ifs lol You have an IDE that takes u to the implementation yuou want to see with a click lol It is crazy to say that just bloating a bunch of logic together with no visual organization is easier to read just because it presents less architectural complexity lol

  • @Michael_H_Nielsen
    @Michael_H_Nielsen 4 ปีที่แล้ว +809

    I think the information is good but please speak faster. I sat the speed to 1.5 :-)

    • @coemgeincraobhach236
      @coemgeincraobhach236 2 ปีที่แล้ว +27

      Haha, I have it at X2, and went to look to make it faster.

    • @midnatheblackrobe
      @midnatheblackrobe 2 ปีที่แล้ว +25

      Had to watch at 2x speed to not ram my head into a wall.

    • @doismilho
      @doismilho 2 ปีที่แล้ว +9

      Lol me too. Funny that the top comment is exactly this

    • @TexMackerson
      @TexMackerson 2 ปีที่แล้ว +56

      He's explaining MStates to people who write spaghetti code, he HAS to go slow

    • @coemgeincraobhach236
      @coemgeincraobhach236 2 ปีที่แล้ว +12

      Ah to be fair it is a good video. More a reflection of my impatience than anything 😅

  • @davedoublee-indiegamedev8633
    @davedoublee-indiegamedev8633 2 ปีที่แล้ว +188

    It:s not a bad approach but it can devolve into an inheritance hell with 30 classes for something.
    If you wanna keep things simple, you can do the same by just organizing your code well with functions. A different function will be called depending on the conditions. So you will treat functions as objects.
    Also, don't have variables like isDead or isJumpinh. Have functions that return the result instead (e.g. isDead() returns true if HP is 0). That way you avoid setting the state, you always have it ready.

    • @ozzyfromspace
      @ozzyfromspace 2 ปีที่แล้ว +7

      I agree with you. Functions are more ergonomic imo

    • @magnusm4
      @magnusm4 2 ปีที่แล้ว +2

      You still need to check those conditions and the code within can become big.
      How do you choose what function to run when? You still need to run through conditions on which function to use.
      A grounded function returns grounded. So now you have to check to run that function.
      Unless you use delegates and return a function that should be run.
      So it returns the function to run.
      State machines are helpful when you work with characters in characters.
      For example crouching increases your jump height, let's you deploy certain objects, different abilities don't work, other abilities change and some are the same.
      You might also have to do some other checks like a ledge grab when falling but also a ground and wall check.
      One way is how he showed with inheritance. Idle and running states inherit the grounded class and execute that functionality while jumping inherit InAir and does that functionality, or doesn't. It's your choice.
      Have a character state that has an input function, when you're stunned then you don't call your inherited state's input function cause you don't need that when stunned.

    • @KojiKazama
      @KojiKazama 2 ปีที่แล้ว

      Depending on the state that you're in, your child class may have functions not in super.
      Example the JumpingState will likely have cool-downs, allowed interruptions, combination actions, and variables that are not in the other states. This works out clean because if writing all in one class, you need to keep track of your private vars on which is the jumping cool-down, attacking cool-down, dashing, etc.
      And you have to build additional code that says if you are doing x and not y and z is not happening, this is ok, but if your state is Jumping, the input doesn't even have the action for y and z so you cold never perform it.

    • @notBradYourself
      @notBradYourself ปีที่แล้ว

      Agreed. I'd probably just opt for making CharacterState an enum and have that handled it in it's own function.

  • @TGameDev
    @TGameDev 2 ปีที่แล้ว +10

    Imo you could also save the headache by implementing functions and guard clauses. So for instance that nested nightmare would look more like this:
    If (isDead) return 0; // he ain't moving anyways
    If (!isGrounded) return 0;
    If (attackPressed && isIdle) attack();
    // Etc... also, to those curious you don't need brackets if there's only one action following the statement.
    Notably a break or continue (in place of return) work better in certain scenarios, such as being in a for loop.
    Hopefully this helps.

  • @ZeroSleap
    @ZeroSleap 4 ปีที่แล้ว +67

    I believe the CharacterState would be better as an Interface,as there's no real reason for a base class implementation of handleInput.
    Plus the interface route enables inheritance of another class or interfaces.
    If a base class implemantation of handleInput is needed,an abstract modifier for the CharacterState class can be used instead.

    • @thepatchinatior
      @thepatchinatior 2 ปีที่แล้ว +5

      I think that was the intention but the author wanted to keep it as simple as possible

    • @jarrettonions3392
      @jarrettonions3392 ปีที่แล้ว

      Yes. That is the solution i impleneted last night after learning about them. They work great! Agreed better. Good to learn inheritance too as it's something ive been hearing a lot about too.

  • @Gortart
    @Gortart 2 ปีที่แล้ว +356

    You generally don't want a seperate class with just 1 method to override because you can just use delegate. And rather than returning a new instance of the state, the states should return a state flag that the caller should use to look up what to do next. Enum with a dictionary to look up would work well.
    And this is not really fixing spaghetti code. You would have to constantly make seperate classes for each new state as you add mechanics. If you added silence that stops some of the abilities but not all, you would have to make IdleSilenced, JumpingSilenced etc. The player should have some kind of attack timer and shouldn't be able to attack every frame. So should I make IdleCanAttack even though some attacks are only possible while in the air? Or name it IdleAttackTimerZero and have quite a bad time writing them down all the time? How do you even manage going from JumpingSilenced to IdleAttackTimerZero? At some point you HAVE to use nested ifs or you're just gonna make the state list grow 2x times each time you add something. In the given example, the isDead check should be at the very top of the update method and just return if the player is dead(or just do some being-dead logic then return). Checking isGround and isRunning could be quite confusing and you can add get-only property(something like CanUseBigAbility) and just return isGround && !isRunning. It's pretty much the same, but it's a lot better to manage.
    Spaghetti codes are bound to appear in any kind of complex system. Coder's job is not to eliminate them entirely, but to contain them in a safe box so it doesn't spill to everywhere.
    And haha your mom joke funni yes very funni

    • @mighty3257
      @mighty3257 2 ปีที่แล้ว +4

      Dictionary for the lookup… How did I not think of that? Thanks a lot for the idea.

    • @tatoforever
      @tatoforever 2 ปีที่แล้ว +1

      You described a couple of flaws that state machine behavior model has. And yes, there's no way to avoid some sort of nested if/else branching. Unless the system is so simple but this is rarely the case. In the context of AI, something that is not widely used but helps a lot in the decision making process (eg Switching behavior state), the part that is always prone to spaghetti code, is Utility AI.

    • @Zach-cc4ft
      @Zach-cc4ft 2 ปีที่แล้ว +2

      Yes I agree, I think this is kind of a bad way to approach the problem of spaghetti code, I feel like this creates a problem of making too many classes and things that is harder to manage than it would be to properly manage the spaghetti code of different states and would end up being a lot harder to read. Inheritance is great but I feel like its overused when it comes to things like this where it really doesn't make a lot of sense and actually makes it harder to read/manage.

    • @101touchapps
      @101touchapps 2 ปีที่แล้ว +11

      i read this comment, i turn off unity and shutdown my laptop and throw gamedev dream out of the window. i think i will go work at mc donalds serving burgers. lol. gamedev is hard.

    • @LifeLedLucid
      @LifeLedLucid 2 ปีที่แล้ว +8

      @@101touchapps you're watching vids to improve, if there is something you don't understand, take it as an opportunity to improve even more. I hope you continue your gamedev dream

  • @LordBordNoob
    @LordBordNoob 2 ปีที่แล้ว +15

    Much like others have said, using enums and a dictionary with delegate functions is a much better solution to this. Or simply having functions that take care of each behaviour.
    If you constantly assign new objects and get rid of them like this on the fly, you will inevitably cause more memory fragmentation and a much bigger overhead for the CPU and the garbage collector.
    The 'new' keyword is something that should be used only when there is nothing else that you can do.

  • @mintesnotmelese6552
    @mintesnotmelese6552 4 ปีที่แล้ว +33

    Men Please I want a bunch of Tutorials on State machine pattern programming, You're now officially my fav TH-camr. keep doing this stuff a lot I love it! :)

  • @garebeargaming9281
    @garebeargaming9281 4 ปีที่แล้ว +6

    Spent the past week having a headache and a half trying to fully implement a state machine. And damn you just alleviated my headache.

  • @3_14pie
    @3_14pie 3 ปีที่แล้ว

    You have no idea of how much this video changed everything for me

  • @NikolaZagorac
    @NikolaZagorac 2 ปีที่แล้ว +4

    I'm about 20% done with my game mechanics, and have around 20 classes already... It seems like the more I unwind my code, the more complex it gets, but the more complex it is, the easier it is to work with.

  • @andythedishwasher1117
    @andythedishwasher1117 2 ปีที่แล้ว +6

    This was extremely understandable and helpful. State management seems to be one of the trickier initial hurdles in Unity, so I think your subject matter was on target as well.

  • @seb6861
    @seb6861 4 ปีที่แล้ว +48

    I still don't consider my self a game dev until i could make at least one game and not just little project that i do to learn different stuff.

    • @BobrLovr
      @BobrLovr 3 ปีที่แล้ว +32

      no matter where you are in your skillset, you can make a full game. Your coding isn't holding you back, it's your project management skills. You can make a full game just using if statements and the update method .

    • @PearlyMishima
      @PearlyMishima 3 ปีที่แล้ว +2

      @@BobrLovr true

    • @chronosbat
      @chronosbat 3 ปีที่แล้ว +3

      @@BobrLovr Lol I remember doing that on roblox studio a long time ago (code is in lua) before switching to Unity so that's 100% true.

  • @7oca7hos7
    @7oca7hos7 2 ปีที่แล้ว +107

    Well, idk. I think using oop for this problem is a bit of an overkill. You just could have handled all the conditions inside the attack() function, using boolean operators and the return keyword to avoid nesting. The user presses the attack button, then the function is triggered and it checks the conditions for doing the attack. In this way you have all the conditions in one place for that specific context, making the update function much cleaner. I think also that the code will be easily understandable for other people, and for you too when you'll read it after a while

    • @GlitchyPSI
      @GlitchyPSI 2 ปีที่แล้ว +6

      Guard clause 💙

    • @patrickp4175
      @patrickp4175 2 ปีที่แล้ว +16

      It was for the wannabe gamedevs I think. To show them how c# can be used. The guys which want to do all the things... except learning the fundamentals.

    • @durrium
      @durrium 2 ปีที่แล้ว

      I agree with you man, this was way overkill

    • @accountdua9375
      @accountdua9375 2 ปีที่แล้ว +9

      @@durrium The demo that he shows us just a example... as he said it's really good to use this pattern to make a big game..

  • @hellhunter9478
    @hellhunter9478 ปีที่แล้ว

    This tutorial is pretty straight forward I like this approach it would make the player class look more human and also you get rid of the entire if statements from that class.

  • @2simmy2
    @2simmy2 2 ปีที่แล้ว +62

    I would recommend keeping your state as an enum instead of different classes then have a switch that shoots off to their own methods. Doing so will leave access to common data accessed by multiple states. This will also allow access for multiple states at once by using a flag enum if it's necessary (but i would recommend avoiding it)

    • @milankeravica7172
      @milankeravica7172 2 ปีที่แล้ว +4

      Wouldn't that make it a state machine, while the video demonstrates the usage of a state design pattern?

    • @TheExiledMeriler
      @TheExiledMeriler 2 ปีที่แล้ว +11

      You wouldn't achieve same code design idea with enum states.
      You end up with just creating a switch with going through all the enumeration, keep updating it with new states you added, keeping everything for function in single place. This solution doesn't really need give any need in touching anything but states themselves directly, so it won't break random stuff you could forget in main behavior code

    • @2simmy2
      @2simmy2 2 ปีที่แล้ว

      @@TheExiledMeriler That's a good point. An alternative to adding a ton of classes would be to use some form of delegate that gets switched out when changing the state of the class. This is only useful when most states need to access most data from the root class so making multiple classes would be redundant.

    • @DoorThief
      @DoorThief 2 ปีที่แล้ว +3

      Not to mention that you won't have a bunch of heap allocations that need to be garbage collected

    • @Hersatz
      @Hersatz 2 ปีที่แล้ว +10

      Enumeration is the same as using a bunch of boolean.
      It also push your code towards the switch anti-pattern, which is very bad.
      State pattern (its a pattern for a reason, widely used -check the gang of four for other patterns to start learning this incredibly usefull stuff-) allows the programmer to set up specific states where methods called in said state either do something, do nothing or do something different than the other methods.
      Usually all state should be implemented (i.e. they have a parent class) through abstract class or an interface which dictates what methods are to be implemented in every state of the state pattern.
      A good, simple, example would be a player grounded state, player airborne state and a player dead state.
      All three would have some theoretical methods :
      - Jump()
      - Move()
      - Attack()
      Player Grounded state:
      All three methods do something
      Player airborne state :
      Jump() does nothing (player is airborne) | Move() see movements halved for slight midair control | Attack(), in this specifc use case, does nothing.
      Player dead state :
      Does absolutely nothing since the player is dead. No movement, no attack.
      Note that a few different ways of managing which state is the current state exists (state enter & exit, state handler, state update, etc. ).
      I cannot stress enough how powerful this pattern is to get rid of conditionnals.
      It is also very easy to implement when you understand its functionalities.
      Plus, it is highly modular in nature, and easily respect the principle of being [Open for extension, closed to modification] -See SOLID principles-.
      You may even use it as a hierarchical state machine, where states exists inside of other states.
      Great stuff.

  • @spectrecular9721
    @spectrecular9721 2 ปีที่แล้ว +19

    IDK, I think this boils down to whether you want your code to "look pretty", or you want a more performant/optimized game.
    This approach would probably be much more expensive than other options... certainly more expensive than nested 'if statements' checking conditions.
    Or just use a 'state' enum, or a single 'PlayerState' class. No need to over engineer anything.

    • @dede6giu
      @dede6giu 2 ปีที่แล้ว +2

      not really, as nesting if statments usually causes more expense to the processing than using classes

    • @spectrecular9721
      @spectrecular9721 2 ปีที่แล้ว +10

      @@dede6giu IDK if its handled any differently in IL code, but if statements are one of the most basic and primitive opcodes supported by some of the oldest CPUs, whereas classes typically require building and managing virtual tables and their respective address spaces, which are definitely more than 1 line of asm code

    • @lanik8163
      @lanik8163 2 ปีที่แล้ว +10

      I always find it funny when people say your code is bad (long and error prone) and then proceed to show you something even longer and much harder to manage.
      I'd say that as long as you think about the order of your conditions carefully and group some of them together or use delegates it'll result it better and more readable code.
      And like you said, you won't be wasting memory just to call a fucntion.

    • @detuneCris
      @detuneCris 2 ปีที่แล้ว +6

      @@dede6giu not at all lol, get your facts straight.

    • @PixelPressChannel
      @PixelPressChannel 8 หลายเดือนก่อน

      Bruh, performance is useless if the code is HELL to maintain lol especially if more devs are gonna work on the code. Just imagine nesting states for a huge game with 100 different states lol There is just no way, it definitely needs cleaner architecture in order to scale.

  • @aleksandarpantic8732
    @aleksandarpantic8732 4 ปีที่แล้ว +73

    Put it at x1.25 speed and still slow...

    • @firemind2265
      @firemind2265  4 ปีที่แล้ว +38

      Maybe put it on x2.00 then ? :D

    • @aleksandarpantic8732
      @aleksandarpantic8732 4 ปีที่แล้ว +8

      @@firemind2265 good video, I'll give you that. Keep pushing, very good video editing 👌😁

    • @Lantertronics
      @Lantertronics 2 ปีที่แล้ว +4

      I think it's paced perfectly. I find that a lot of polished, high-quality Unity tutorials (like Brackeys) go too fast and I have to rewind a lot.

    • @1001HELL
      @1001HELL 2 ปีที่แล้ว +1

      I'm dumb and need this pace.

    • @giampaolomannucci8281
      @giampaolomannucci8281 9 หลายเดือนก่อน +4

      it's better to speed up a slow video than slow down a fast one, audio is less messed up

  • @KojiKazama
    @KojiKazama 2 ปีที่แล้ว +4

    I really like this approach. About 5-6 years ago when I did some Unity dev, my code looked exactly like you described. If if if if if if attack1(). This really helps with chaining actions and tracking things like attack combos. Now you can easily specify in each state what the possible actions are. Attack1State will have ATTACK = Attack2State, ATTACK + JUMP = AerialAttack1State. Thank you for sharing.

  • @whoisthiswhoknows
    @whoisthiswhoknows 2 ปีที่แล้ว +6

    I started comp sci this year and this is the first coding video I've actually understood. So I guess that class is useful.

    • @firemind2265
      @firemind2265  2 ปีที่แล้ว +3

      Happy to hear! Stay on it!

  • @roguedrones
    @roguedrones 2 ปีที่แล้ว

    Firemind is a genius Nivmizzit would be proud of.

  • @polarisinglol
    @polarisinglol 2 ปีที่แล้ว +5

    Awesome video! I recently got into Unity due to an assignment in my University which will be graded and am really loving it so far. Even though I already knew most of the stuff in the video I have to say it was a pleasure to listen and watch and I think you definitely helped a lot of people who are just getting started with programming languages and coding in general :)
    Thank you!

  • @juaecheverria0
    @juaecheverria0 2 ปีที่แล้ว +2

    Come back, this tutorial was perfect i need more.

    • @firemind2265
      @firemind2265  2 ปีที่แล้ว +2

      I'll be back 8-)

    • @juaecheverria0
      @juaecheverria0 2 ปีที่แล้ว

      @@firemind2265 you the best, cant wait.

  • @thatoneuser8600
    @thatoneuser8600 2 ปีที่แล้ว +55

    12:28 that conditional statement looks like something that could easily be duplicated across multiple states, which isn't a good thing. It also violates TDA (Tell don't ask principle) where you're querying the state of Input and performing operation based off of the returned value, so to me, it would make sense if the update state functionality based off input would be in some update method in the Input class that returns a state, depending on the factors you require for it to return the proper state. Then, all you would do is return the result of that method in handleInput()

    • @Neran280
      @Neran280 2 ปีที่แล้ว +2

      If I undestood you correctly you want to encapsulate the querying of the button press and the state transition into an own Input class and that class returns the CharacterState object? The Input system that unity provides is already an encapsulation, but it lacks some feature. So its good to define an own Input class that can also for example provide interfaces to deactivate inputs during cutscenes, etc. But I do not think that this class should also handle the state of your character. Also because this is a state machine, the Input class must have knoledge about the state transitions. Like into what state are you transitioning when in the idle state and jumping? Or isnt this possible at all? So in my opinion this transitioning logic makes more sense to be part of the corresponding state class.

  • @kreed1415
    @kreed1415 3 ปีที่แล้ว +61

    State machines rule, however I would suggest you look into a more efficient solution that has less boilerplate code. If you have to create a brand new class for every state it gets incredibly tedious as your game grows. Consider making a StateMachine class that inherits from monobehavior that has a dictionary of which represents state then simply run the method for each state. it also makes declaring each state very simple and concise

    • @LuRybz
      @LuRybz 2 ปีที่แล้ว +7

      could you provide an example? Interesting

    • @johnleorid
      @johnleorid 2 ปีที่แล้ว

      Running code inside of states is a problem on it's own when it comes to character controllers. For example: if your player can jump, you will have the code for jumping in the grounded state, in the idle state, in the wallrunning state, in the sliding state, ... you get it.
      So I found it way better to have states which just run abilities (like the jump ability) - so there is only one state class and all it does is passing Update() down to it's referenced abilities.
      Professional Character controllers like the one from Opsive (asset store), are using the same pattern.
      And for everything else than characters or game state, I'd avoid using state machines and go with a component pattern instead.

    • @casefc3s
      @casefc3s 2 ปีที่แล้ว

      @@johnleorid Opsive's code is not a good basis for good programming practices. Yes it works and has a lot of functionality, but it is very poorly structured. I wouldn't call it "professional" beyond that they sell it as a product and it does well purely because it has a lot of functionality. Maybe it's changed recently, but those huge 10k line classes or whatever it was are a great indicator that things have not been well thought out or maintained.

    • @casefc3s
      @casefc3s 2 ปีที่แล้ว

      Why is making a class more tedious than writing an Action? Creating a state that implements focused interfaces is much more extensible and controlled. A couple hot keys and a C# template are all that's required. The Dictionary is an extra step that seems like it will end with doing unnecessary string comparisons against a big list of possible states somewhere down the line.

    • @delanmorstik7619
      @delanmorstik7619 2 ปีที่แล้ว

      @@casefc3s Because you will have class for each state AND method for ..each action in each state object. If you have worst case scenario, depending of you needs, you will end up with 10 diferre t classes for state, each of them having 10 methods.. jump, attack.. etc 100 methods!!!! If you did only use if if if.. you would have less than 100 if for sure. And also the example in the video was terrible example. The author should have chosed more complicated example where his solution would be obviously superior.
      Also the code itself was tons of unnecessary nested ifs. Why would you have nested if in each if if the player is dead. If the player is dead just return false. I hate when people give pseudo-example for clarity... Making the example dangerous! Now tons of new developers will do this solutions in their game without trying to find a better one for themself!

  • @RawDawginRoLo
    @RawDawginRoLo 3 หลายเดือนก่อน

    I like the speed of the voice. I can always adjust it but for a beginner like myself it allows me to keep up

  • @ScooterCat64
    @ScooterCat64 4 หลายเดือนก่อน

    As long as the code does what it's supposed to without performance issues and is easy to read and understand by the programmer, the code is fine.

  • @ftwgunnerpwns
    @ftwgunnerpwns 2 ปีที่แล้ว +6

    I really like your explaining speed, it's way easier to digest than most tuts, thank you!

  • @sonsai10
    @sonsai10 4 ปีที่แล้ว +14

    tutorial was so great and funny, can't wait for the next advanced coding topic

  • @notarvis
    @notarvis 2 ปีที่แล้ว +1

    I was confused when I couldnt find skip ad button at the start of the video, because I thought I was being offered yet another ai tool :D

  • @astrahcat1212
    @astrahcat1212 ปีที่แล้ว +2

    Of course, if you REALLY want simple and easy code, you could just not use oop at all and make everything a public static method (so like procedural programming).

  • @CastielQuinzel
    @CastielQuinzel 2 ปีที่แล้ว +2

    I'd rather code spaghetti. My avatar uses a very long list of code to make sure he dies when he is supposed to, doesn't go through walls, picks up items, opens doors, go to different rooms and use objects.

  • @ChinchillaDave
    @ChinchillaDave 4 ปีที่แล้ว +49

    Well produced, paced and edited educational content with a hint of humor. Great explanation of FSM!
    Excited to see what you do next Firemind.

  • @nikolatasev4948
    @nikolatasev4948 2 ปีที่แล้ว +13

    For a large game this is great, but for a small game having the states as enums is more than enough. Then handle input can call the right methiod like HandleInputStanding, and that can have a bunch of early returns to keep the if soup at bay.

    • @KawaiiKodeDaddy
      @KawaiiKodeDaddy 2 ปีที่แล้ว +4

      Absolutely! Actually, it really just depends on the use case even in larger games. State Machines should only be used in cases where there is complex state driven behavior. Otherwise, that becomes spaghetti code.
      Even the given example is far too simple to excuse a complete state machine.

  • @algorithm1313
    @algorithm1313 2 ปีที่แล้ว

    Not a game dev
    A soft dev
    Nice video super helpful 🔥🔥

  • @dimak.6323
    @dimak.6323 4 ปีที่แล้ว

    The first question got me yelling YESSSS ! I was looking just for that because I didnt know what alternatives do I have with writing code ! Thanks a lot man!

  • @kingofroms7224
    @kingofroms7224 3 ปีที่แล้ว +2

    Wtf why youtube cant suggest you to me earlier but now thanks I found you keep upoloading

  • @sealsharp
    @sealsharp ปีที่แล้ว

    So this was recommended to me by youtube as the thing i should absolutely watch on this beautiful sunday morning.
    And this seems really overengineered to me.

  • @Gomace
    @Gomace 9 หลายเดือนก่อน

    The only thing that I personally did not quite understand, and had to look up, was what virtual and override did. Although I understood that it did the job you wanted it to do, I did not know why these two new things were necessary.
    According to what I found while watching this video:
    Virtual and Override actually come in the same category as another word called Abstract. These three words are all related to inheritance. (There are a few more like Interface and internal that are relevant to this conversation, but for this example using these aforementioned 3 should be enough.)
    Virtual and Abstract are both keywords to be used almost in the same way by the class you want other classes to inherit from, as shown in the video.
    The difference being that Abstract forces the child class to Override it with a new method/function, while Virtual says you can if you want to; but calls itself instead if the child class does not Override it.
    This is useful to know because Abstract classes can just be empty, with only the name and passing argument requirements being created, while Virtual presumes that you've created a usable method/function in the parent class.
    I hope this was clear, and I hope it was correct. I only read one forum post for this, but it seemed logical.

  • @magnusm4
    @magnusm4 3 ปีที่แล้ว +3

    I've seen Table Flip Games's tutorial and the great Unity finite state machine tutorial.
    But honestly it's really complicated. You send a new state from another state, which I honestly find scary to land in a soft lock.
    Flip Games makes a Finite State Machine class that handles everything and makes a reference to it in his main player class.
    And the guy in Unity's version he handles the current state in the player's main control script. And even has a function for transitioning to a new state where he sets the new current state and calls Enterstate, passing in his player class so that the state can access his Rigidbody and move it from the state.

  • @elian_geser
    @elian_geser 8 หลายเดือนก่อน

    Hey Man! Super nice! I def learned smth from this video, smth great! U being a chill talker made it relaxing to learn. Some parts i felt like u took some time to get to the point but otherwise it is a super well explained tutorial👍
    Thank you a lot!

  • @phatpingu
    @phatpingu 3 ปีที่แล้ว +1

    Duuuuuude... Your explanation.. You GET IT! Sometimes, when people explain things, they forget what it is like NOT to know something.. and assume that the listener is going to understand each thing.. but you managed to put your self in my shoes and YEAH!
    The result was: I was 100% able to follow everything you said, step by step.. on 2x speed! :-p hehehhe

    • @phatpingu
      @phatpingu 3 ปีที่แล้ว

      Subscribing in 3... 2... 1...

  • @kalpolproductions8558
    @kalpolproductions8558 2 ปีที่แล้ว

    This guy slower than my brain!
    now i can understand!
    THANKS!

  • @matthewmathis62
    @matthewmathis62 2 ปีที่แล้ว +1

    Wow! You just revealed the state example, and it makes sense. It's a good way to write code. I like it!
    I'm glad you've said this, because I'm sure that I've written spaghetti code before.
    Coding is one of my favorite things to do, because it's so fun! And I appreciate you taking the time to make this tutorial.
    I would like to all of the concepts like the one in this video, shared conveniently in one TH-cam video. Perhaps you're up to the challenge? Hopefully someone is.
    Thanks,

  • @Rexvideowow
    @Rexvideowow ปีที่แล้ว +1

    I prefer the simplistic approach. if (AllTheseChecklists()) {...} That way, the code is readable, we know we are checking for things, and all those things can be isolated to the single function. As for AllTheseChecklists() itself, I prefer to use the traditional method of using a result. bool result = false; then you go: result = IsCharacterGrounded ? true : false; then on the next line you go: if (result) { result = IsCharacterAlive(); } and continue on in that fashion: if (result) { result = HasEnoughResources(); } and so on. This way, your code will always stop at the first point of failure and will return result; at the end of it. It is efficient.

  • @vizualwanderer
    @vizualwanderer 2 ปีที่แล้ว +4

    state machines are cool and have intrigued me a lot, however, once you're in Jump state you don't really handle "just jump functions," do you? You also need other functions in there to transition back/to run or idle state, no? So you're pretty much creating a class for every state and set state shares elements that invoke other states in them besides there main function.

  • @espermeadows1882
    @espermeadows1882 2 ปีที่แล้ว

    Your way of teaching is sooo so nice, thank you 🙏

  • @DrClementShimizu
    @DrClementShimizu 2 หลายเดือนก่อน

    interesting to see state implemented as a class... i can see the benefit

  • @ridlr9299
    @ridlr9299 2 ปีที่แล้ว +1

    CharacterState should really be an abstract class for this example

  • @makeshiftgames3799
    @makeshiftgames3799 2 ปีที่แล้ว +1

    watch it on 1.5x speed, and it's about normal

  • @kotted
    @kotted 2 ปีที่แล้ว

    Nice. Recently learnt about the virtual functions so it's really nice to find use for them here

  • @APNDisco
    @APNDisco 3 ปีที่แล้ว

    People who disliked were offended by the mom joke 😂 great work! You earned a new like and sub

  • @diligencehumility6971
    @diligencehumility6971 2 ปีที่แล้ว

    When you made the "your mom" joke, I had to leave a like!

  • @attenurmi936
    @attenurmi936 2 ปีที่แล้ว

    Thanks! I've just started geting into Unity and coding and have already done a lot of if-soup. :D So this saves me a lot of headache in the feature.

  • @parsnipthepossum8962
    @parsnipthepossum8962 2 ปีที่แล้ว

    I had to read the text in the thumbnail a couple times to realize it didn't said "code not better spaghetti" but "code better not spaghetti"

  • @ludicrouS_406
    @ludicrouS_406 4 ปีที่แล้ว +2

    I have just discovered Educational ASMR 😂.
    Btw the video was great and really well explained, thank you

  • @saisankeerthredybommana754
    @saisankeerthredybommana754 2 ปีที่แล้ว

    Very nice video bro 👍🏻

  • @Larock-wu1uu
    @Larock-wu1uu 2 ปีที่แล้ว

    You got me at "sitting in the basement"! 🙂

  • @teawacrossman-nixom7696
    @teawacrossman-nixom7696 2 ปีที่แล้ว

    Thank you I love the concept, food for thought

  • @gizel4376
    @gizel4376 2 ปีที่แล้ว +1

    really nice! so if i understand well, this line:
    State = State.handleInput(); // is calling the function associated with the actual state, looking for some if statement(or even case i guess) that will either return a new state or the same state ?

  • @goblinslayer6375
    @goblinslayer6375 3 ปีที่แล้ว

    Firemind make your code great again.

  • @dolphin_dog
    @dolphin_dog 2 ปีที่แล้ว

    that drawing could be album art for a cassette tape demo of a punk rock band called F.I.R.E.M.I.N.D.

  • @vorlon478
    @vorlon478 2 ปีที่แล้ว

    Awesome job explaining this complex topic! Keep it up!

  • @raptorswire7212
    @raptorswire7212 4 ปีที่แล้ว +10

    Great tutorial, but it would be great if you would show the whole finished code in the end

  • @TidaliCreative
    @TidaliCreative 7 หลายเดือนก่อน +1

    0:18 literally how I sat there hahaha

  • @pietrofirmino
    @pietrofirmino ปีที่แล้ว

    Success my friend!

  • @simoxeh
    @simoxeh 2 ปีที่แล้ว

    I liked the tutorial and I think I would have liked to see the jumpstate code also to get the full picture. I'm still confused as to how it works. I might have to write coffee and see myself. thanks for the starting point though

  • @chips409
    @chips409 2 ปีที่แล้ว

    Everybody gangster until the Italian guy starts coding spaghetti

  • @Gummypuss
    @Gummypuss 6 หลายเดือนก่อน

    I know I want large diverse move system this may help me in the future when I actually begin coding that nightmare.

  • @1221fun
    @1221fun 2 ปีที่แล้ว

    thank you!!! it's really useful conception for me!!

  • @francescagreetham1804
    @francescagreetham1804 2 ปีที่แล้ว

    I really enjoyed this!

  • @pwnwin
    @pwnwin 2 ปีที่แล้ว

    I’m pretty sure this video taught me how to make double jumps among many other things lol

  • @Jamesthe1
    @Jamesthe1 2 ปีที่แล้ว

    Using objects for states is over-engineering imo. The real sin here is not using an input event and state enums.
    When input is received, it should have its own separate function. This can be achieved by creating a function with a name like "OnInput," then adding the function to InputSystem.onEvent with +=, and then subtracting it in OnDestroy(). Relevant states should be checked and updated here.
    Next, our state. "Dead," "Jumping," and "OnGround" never happen at the same time, so it's better to put these in an enum and check for the desired state in our OnInput function. As per movement (if we don't want to create separate JumpingMoving states), we can have another state enum to contain "Still," "Walking," and "Running." Adjust this and compact it to how you desire; the code is much more flexible however with a single state enum.
    Our objective here is to make our code not just clean, but manageable too. If we create objects, this will lead to "clean" code with extra work.

  • @swiatstdio5977
    @swiatstdio5977 2 ปีที่แล้ว +1

    > "better coding"
    > method names starting with lowercase character
    Choose one

  • @tin2001
    @tin2001 2 ปีที่แล้ว

    4:10 - I feel old thinking about setting the school Macs to all play that quack sound... Back in 1993.

  • @favour5442
    @favour5442 2 ปีที่แล้ว +2

    When 1.5x feels perfectly normal 🌝

  • @cb2818
    @cb2818 2 ปีที่แล้ว

    earned my sub. you are a great teacher.

  • @maikeltoxix1716
    @maikeltoxix1716 2 ปีที่แล้ว

    would like to see more advanced coding. most tutorials are kinda plain..
    thanks, for a newbie like me its good understandable

  • @romainsalvan6331
    @romainsalvan6331 4 ปีที่แล้ว +2

    I think a much cleaner way to handle state management is to use an enum CharacterState

    • @TheLucausi
      @TheLucausi 4 ปีที่แล้ว

      could be much cleaner, but unmanageble sometimes. Do you want to fill enums with states or simply create a new state class that handle the entire state?
      If you think about it, where do you handle this enums check? it's here the trap.

  • @NikCification
    @NikCification 2 ปีที่แล้ว +2

    This video and tip was amazing!! Thank you, Sir. Please make more videos like this and provide more great coding tips. Thank you.

  • @noli-timere-crede-tantum
    @noli-timere-crede-tantum 2 ปีที่แล้ว +1

    5:09 so your character can't jump unless it's idle? Is that so you can avoid needing extra conditional checks?

    • @AlFredo-sx2yy
      @AlFredo-sx2yy 2 ปีที่แล้ว +1

      that's because he's lame at programming, simple as that.

  • @hans_xwh
    @hans_xwh 2 ปีที่แล้ว

    I like to use like a thousand variables, it makes me look like im coding a lot :)

  • @betterlifeexe4378
    @betterlifeexe4378 3 ปีที่แล้ว +2

    enum State { States, Here, Call , Methods, Or, Coroutines, When, Processed } internal void changeState (State state){} //this keeps it all in the same class and IMO more readable :)

    • @Anthonyfchannel
      @Anthonyfchannel 3 ปีที่แล้ว

      I do it so, but when I think of it, It would be way more simple to have a class for each state. It keeps the code shorter and it's easier then to add a new state without modifying the parent class.

    • @betterlifeexe4378
      @betterlifeexe4378 3 ปีที่แล้ว

      @@Anthonyfchannel ... or you can add a new state by adding an enum and method. I mean they both work, but I just don't see how managing several classes encapsulated by a namespace or document is easier than managing several elements in an enum at the top of a class encapsulating several methods. Nor do I see how it would be shorter or quicker.

  • @TheKr0ckeR
    @TheKr0ckeR 3 ปีที่แล้ว

    I like your humour! Thanks for great guide

  • @bugsephbunnin4576
    @bugsephbunnin4576 2 ปีที่แล้ว +1

    This is literally what I was looking for, thank you

  • @dead.9628
    @dead.9628 2 ปีที่แล้ว +3

    Apparently the AND operator DOESNT exist

    • @liam3491
      @liam3491 2 ปีที่แล้ว

      Your code would still be a mess to maintain, AND operator or not. Use proper design principles.

  • @Spaceman68ok
    @Spaceman68ok 2 ปีที่แล้ว

    Would it be better to make a CharacterState's default method return IdleState? Or maybe make a CharacterState class an interface for it to not have a default method and to not write virtuals and overrides?
    I'm not really experienced so I want to know.

  • @torch4762
    @torch4762 2 ปีที่แล้ว

    God damn, the intro is fantastic. How would using enums compare?

  • @richardpitak9669
    @richardpitak9669 3 ปีที่แล้ว +2

    why not to use logic operators?

  • @Basil13ful
    @Basil13ful ปีที่แล้ว +1

    could be nice to set CharacterState as abstract and its method "handleInput" too, to force its child classes to implements it, and to prevent an parent instanciation :)

  • @Zabzuro1
    @Zabzuro1 4 ปีที่แล้ว +4

    Creating a new object for every input is a terrible design choice. In your way, you do not change the state, you create a state every time you want to change state. More "correct" way to achieve state machine thing is, once you need a state just simply create it when you want to change the state don't return a new state, just find the same old state's reference and return it instead.

    • @TheLucausi
      @TheLucausi 4 ปีที่แล้ว

      I agree with the perfomance issues that this guys do. Allocate a new state everytime we need it it's not worth at all. Instead create a state object that is accessible in easy way.

    • @firemind2265
      @firemind2265  4 ปีที่แล้ว +1

      Hey there,
      not sure I get your point. Are you saying that if there is input that does not change the state, returning the old state is more efficent? Because that is pretty much what I propose here (see 13:47). If the input does not affect state, return this. Which is the reference to the previous state. But I'm probably misreading your comment. Can you maybe elaborate a little bit further?

    • @firemind2265
      @firemind2265  4 ปีที่แล้ว +1

      Hey there, thanks for the comment.
      I totally get your point, however I believe these are two different approaches in programming you can take. Yours is more on the object oriented side, where one object contains the state over its lifetime, while the one I'm proposing here is more on the functional side, which imposes that objects are immutable, which means if you wan't to change the object, you rather create a new one. I get that this may seem as it would introduce performance issues, however due to garbage collection and modern hardware creating new Objects will 100% not be the performance bottleneck of the game unless you are building games for very low end hardware like Arduino etc, but then you probably don't want to use C# and Unity in the first place.
      But yeah you can 100% also go with the more Object oriented approach, however I have found this one to be better read- and maintainable, in the end it comes down to what you feel most comfortable with.

  • @zielony1212
    @zielony1212 2 ปีที่แล้ว +4

    Yandere Dev should watch this video...

  • @notcooljustlame
    @notcooljustlame 2 ปีที่แล้ว

    Love the slow tslking

  • @maow9240
    @maow9240 2 ปีที่แล้ว +1

    is it just me? setting video speed to 2X feels like just a normal speed video?

  • @FurquimRafa
    @FurquimRafa 3 ปีที่แล้ว

    Great video! I do not consider myself an advanced programmer and I could understand everything

  • @sup3rsmash8
    @sup3rsmash8 3 ปีที่แล้ว +1

    I would probably create the states in each their own respective field before the player spawns instead of creating a new one every time a state needs to be changed, just to save on memory garbage. But other than that, good tutorial!

  • @TheBoxyBear
    @TheBoxyBear 2 ปีที่แล้ว

    Interesting idea, however it can lead to lot of duplicate code for checking in out and creating states, especially when actions are valid in multiple states.
    What I would do is check inp at a centralised space and call the methods in the state related to the various actions the player can take. The base state provides empty implementations for each one and each state specific class only has to worry about implementing the valid actions its state.

    • @TheBoxyBear
      @TheBoxyBear 2 ปีที่แล้ว

      Also this really only works with single state and not combinations of states. You can always mimick them by creating a new state that babeces as two existing states combined but you will end up repeating code since you can't reference instance methods of a now non-existent state.
      Another completely different approach would be to define the state as a set of properties like AttackReady, JumpReady, Stunned. Instead of having to check everything when performing an action, you can just reference the property as a boolean and do the action if the property says the state allows it. You can also have the getters call other getters to simplify them too. You can start by defining each state property as an auto-property you assign manually somehwere and as your add mechanics, you can redefine the properties with a custom getter without having to change state checks

  • @Havii
    @Havii 3 ปีที่แล้ว

    This video speaks in all languages. German, Dutch, British

  • @Мистер-р9щ
    @Мистер-р9щ 4 ปีที่แล้ว +2

    Keep on keeping on! Great tutorial, thank you