Incredibly underrated tutorial! I've used this in my last two games and it's a total game changer, coding a state machine makes code so much cleaner and organized, and after expanding on it to also account for triggers and collisions, there are virtually no limitations. I've tried using the animator or enums to get similar behavior, but this is so much less convoluted as it isn't nearly as reliant on bools and if statements. The tutorial uses a player controller as an example but using this for enemy AI is also great! And I haven't even mentioned what this taught me about inheritance , thank you so much for this!
Thank you so much for your nice comment! I'm really happy you liked the tutorial and it helped you with your project :) Yup, FSMs are a nice way of structuring "basic" AI behaviour, too!
@@Maskeowl Hi :) So it depends on the exact architecture of your FSM, but basically: any state where the collision can occur should contain the collision check logic. For example, here, both the Idle and Moving states should probably handle the damage routine, so you'd need to include it in both states. But if you have that sort of "global" behaviour that you want to share between multiple states, then you may want to look into hierarchical FSMs - and I've made another tutorial on those if you want, over here: ruclips.net/video/OtUKsjPWzO8/видео.html Hope it helps, cheers :)
@@minapecheux am i doin it wrong ? because i cant add onCollisionEnter void to states so i did it at MovementSM it look like its working , also i saw that video thanks tho but i think i need a bunch more neuron and Iq to understand lol
@@Maskeowl Ah yes, the reason you can't add OnCollisionEnter to the state classes is because those are simply "pure" C# classes, but OnCollisionEnter only works inside a class that inherits from the Unity built-in MonoBehaviour class! So indeed, you either have to catch the collision in the higher-level StateMachine-derived class (here, the MovementSM) and then warn the states, or not rely on the OnCollisionEnter :)
I'm a year late, but glad I found this. Recently started game dev again and I was pulling my hair with all the if statement logic. Time to practice this. Best tutorial/explanation I've found! 😁
This was so helpful! I am making my first game in Unity after a while of working with Godot, so it was great to see how you can implement state machines in Unity. Thank you!
This is probably one of the most straight forward concepts I've seen of a FSM done in unity. Though I'm having trouble with implementing it with the new Unity Input System, I still understand just about everything that needs to be done. Your video on hierarchical SFMs also makes the prospect of them seem a lot less daunting to tackle!
Wow, tbh I was worried that implementing an sm was going to be painful that I was almost considering not doing it, but you explained it so well and changed my mind. Thank you for this tutorial, it was very clean and to the point.
Hey! Thank you so much for this tutorial; as someone who has just started with unity and programming in general, this was really helpful and I was able to get my own state machine working for my project!
Hello @Bertrand - for some reason, your comment doesn't show, sorry :/ What I do at 22:10 is that I use a public field I added to my MovementSM class (so in your case the PlayerControl class) called "movingState" and that allows me to reference my instance of the Moving class. It is not a cast ;) So perhaps make sure you did define this field in your PlayerControl class as shown at 20:16? Cheers! :)
Excellent presentation, you gained a subscriber. I am playing with a completely generic HFSM in C#/Unity based on Ian Millington's book AI for Games. In that implementation you don't create new classes for states, instead you pass the State class its actions for the entry, update and exit, as well as its transitions. Basically you inject the logic into the base class. More complicated to follow than this approach in the video (which seems to be the most common), but very flexible and elegant.
Hi, thanks for your really nice comment! :) Yep, I've already worked with that sort of logic injection (although to be honest it was in Python so I didn't have to concern myself with declaring delegates ^^). It's certainly a bit more complex but also more adaptive. In a sense, I feel like it's a first step on the path to data-driven logic definition (Bob Nystrom talks about here for example: gameprogrammingpatterns.com/bytecode.html), which is an absolute gem when done right! (especially in terms of including your designers every step of the dev, and not just spending months re-translating their ideas into code :D)
@@minapecheux I'll definitely have a look. Yes, delegates can be a bit of a pain and with the generic solution you still have the problem of storing or accessing variables from inside your states' actions, whereas with specialised state classes you can do what you want really, so I am still deciding what I want to use.
Hi @RammyRock - for some reason, your comment doesn't show, sorry :/ You're absolutely right when you say that we don't absolutely need the StateMachine reference in the BaseState class, since we "override" it with our typecast in the derived ones! It's just sort of a "habit" I have when writing my abstract FSM classes so that, if my derived FSMs don't typecast it, I still have an easy link to refer back to ;) But you could totally optimize the code and memory management by removing this variable, in this case example!
Thanks a lot! I'm really glad you liked the video :) Feel free to drop a comment or even send me an email if you have further questions - no problems! Cheers ;)
Hello there! So @reendevelops for some weird reason your comment is not showing, I'm sorry, I'm not clear on all the YT moderation rules... but anyway ^^ About your 2 questions: 1. "Can I use this StateMachine for NPC/Monster behaviours?" Absolutely! Here, I'm using user inputs to switch between states, so I get a "Player" state machine, but you could totally have other algorithms and a different logic to automatically switch between states, which would make an AI. For example, instead of waiting for a key to be pressed to toggle to the "moving" state, you could instead look for nearby game objects with a "Player" tag and if they're close enough, move towards them. This would create sort of a "chase" behaviour for your NPC. 2. "If I also use this on my Player, can I add states during runtime? For example, if the player obtains a skill like Dash, would it be possible?" I would recommend keeping the structure of your state machine the same, but locking some transitions at the beginning. So, all your states (the "dash" included) would exist upfront, but first you won't have some boolean flag somewhere saying "canDash = false;". And in your transition to the "dash" state, you first check this flag and abort everything if it false. Then, when your player unlocks the "dash" state, you'll just turn this flag to true and all your transitions will already be ready to play! Hope it's clear :) Cheers!
@@minapecheux Ahh, that would be it. So I'll set up all the possible States in the beginning and just unlock them with a transition along the way. That makes sense. Thank you so much!
I'm at the point where I've seen enough FSM tutorials to completely understand how they work. So I'm mostly looking for the tutorial with the cleanest code to copy for the base class. And I think this might be the one!
I've personally tried two different things: - using the parent FSM manager to have a global data context (but in that case you need to remember to pass this parent object to the state instances :) ) - using a global event manager to completely decouple the states - if you're curious, I've actually made a tutorial on the topic a while ago: ruclips.net/video/EvqdcyTgZNg/видео.html
Great explanation, but I still got question. Is it legal that each state has ability to change StateMachine as a class (changing its current state), when StateMachine itself can do nothing about it? I mean, SOLID tell us that each class must take responsibility for but himself, though in case of FSM it seems to be exactly opposite. That's also lead to a problem that StateMachine class is extremely opened with those public fields inside it, which seems as encapsulation violation. Am I getting something wrong or it's just specifics of FSM pattern?
Hi! I'm happy you liked the tutorial, and thanks for your interesting question :) Yep, that's actually one of the reasons why state machines are "coupled" patterns - because of how they are structured, the only one that knows when to transition to another state... is the state itself, not the machine! Basically by nicely separating the logic of each state in a class, you also force this state to be responsible for all outgoing transitions, since none of the other components in the system know what's going on. Note that to protect your StateMachine fields, you can go from public variables to getters-only with C# properties: this makes them readonly, which can be useful for the dev phase. But it also makes the access a tiny bit slower, so usually, you revert back to public variables in your builds if you want the execution to be as quick as possible ;) I hope it helps, feel free to ask more questions, cheers!
A useful tutorial, thanks. :) I don't know whether I'm missing something, but I just want to ask about the part where you call a function from the parent class, for example: public override void Enter() { base.Enter(); sm.spriteRenderer.color = Color.black; _horizontalInput = 0f; } I got confused because I assumed that Enter() function in the parent class has not been defined. Greatly appreciate the help :)
Hi! I'm happy the tutorial is helpful ;) So the functions are defined in the parent class, although they are empty! That's the cool thing with virtual functions: you can define them with or without prototype in the parent class, and then partially or completely override it in the children. That being said, it's true that here, calling the parent functions is useless^^ it was just a way for me to show people who are a bit new to inheritance how to do this if they decide to add logic in the parent, and want to keep it in the children :) Hope it answers your question, Cheers!
I always wanted to use state machines but it is a lot of extra work and I'm not sure if it is worth for complex controllers that have many states that can overlap and depends on each other, I would rather adding 3 extra checks and not adding 10 extra script that will create a web
Question here! Why does each state have to do base.Enter() / base.UpdateLogic() and such when the base functions themselves are just empty? I thought the point of override functions were so you can just conduct that function inherently, and the only reason you would do base.(corresponding parent function) is so it also conducts the code in the base class's function?
Hello! :) So you have to be careful about one thing: the base function is only called automatically for constructors/destructors ;) Meaning that here, for example: if I override the Enter() function in my Node-derived class, it will only execute the code inside the override, and not the base code! To have both the base code and the overriding one, you need to explicitly call the base function, using base.Enter(). Override functions are a way of specifying the "default"/fallback behaviour declared in the virtual function, but it does not necessarily imply executing such behaviour... so it's actually better that it doesn't do this automatically! (Note that, on the other hand, if I don't write any override at all matching a virtual function in my base class, then it's that virtual function's logic that will get executed) Hope it helps :) Cheers!
@@minapecheux Hello! I understood that part, but my confusion is why you called the base function in your code when the base.Enter() function is EMPTY?
@@arkhtyi9456 Oops sorry - I read too fast ^^ Yup you're absolutely right that here the functions are empty so we could remove this :) Honestly, it was just a way of introducing this mechanic in the tutorial and teaching people about this specific thing (especially if you decide to add some shared logic in the base.Enter() function, be it for debug or actual runtime effects, then you know how to keep it even with the overrides) ;) But thanks for pointing this out - cheers!
@@minapecheux Thank you for the fast and kind reply despite being an almost 2 year old video! I was just worried maybe I was missing something like you still have to do the base function for some inheretence, code invoking magic reason :)
Your Tuto was a Great Help for me, I'm willing to add some buttons instead of keyboard, Do You Have any Advice Where To put a method to detect a Button Click event , in the moving script which requires adding a gameobject or the or The MovementSM ?
Thanks, I'm glad you liked it! :) I guess in your case I'd make some global event system, so that I can click on a button and have this click send a "move left" event (for example). Then, I'd add a listener in the Idle class, so that I can transition to Moving. You might also need your event to have some extra data about the direction you want to move towards, but here I'll let you organise it as you want ^^ Then you should probably have a "on button release" -> "stop" event chain, to go back from Moving to Idle. By the way, if you're curious about this global event system thing in Unity, I made a tutorial on that topic :) ruclips.net/video/EvqdcyTgZNg/видео.html Hope it helps, cheers!
Thanks! Well, actually, this video is a "prequel"/first part, directly followed by a second one on the hierarchical FSMs, over here: ruclips.net/video/OtUKsjPWzO8/видео.html So good catch ;)
Hi, nice video to tell about FSM, but i have some issue here, in the state like idle and moving we casting the MovingSM, how we can change that behavior for let say 5 NPC with difference type?
Hi, and thanks for your nice feedback! So basically if you want to have different behaviours, you'll probably need to create one StateMachine-derived class for each, and for your State-derived classes you'll also need to: - use some data/variables to specialise the instance (e.g. your state's class constructor could receive the name of the animation to load, and so you can use the same class for two NPCs with different animations, just by providing a different name in the constructor) - or make different scripts if it's really too specific to each ;) I hope it's clear, tell me if you want more info! Cheers :)
I've been following this tutorial for a game I'm working on, but I've hit a road block. At 17:15 how do I get the input from Unity's "new" input system?
Hi! I think this page from the official docs should contain all the required migration tips for converting this code to the new input system: docs.unity3d.com/Packages/com.unity.inputsystem@1.7/manual/Migration.html Hope it helps, cheers! :)
Hey! I'm not sure if you will be able to help me or not, but I am implementing this state machine in a small game I am working on but I am having a slight issue. When switching between states, it is changing the value of some of my variables, even though there is zero logic on the transitions that could cause these values to change. The values that are being changed are held in my 'MovementSM' script and I am referencing and changing them from the specific state scripts. Is this the wrong way to do things? If I have been too vague about my issue, I can elaborate further Either way this tutorial and a few others of yours, have been super helpful! Thanks a ton!
First of, thanks a lot for your nice feedback, I'm really glad you liked the tutorials :) About your question: - if you have "global" variables that should be cross-states and impact your entity at a higher level, then it makes sense to store them outside the states; you can put them either inside the MovementSM (if they are roughly linked to movement, like the "speed" in my example), or even in another PlayerManager script for example and then access it... basically it depends on your project structure ;) - not sure why your values are changing though... it's a bit hard to tell you out of the blue and without the code, sorry ^^ If you want, you can send me your scripts and/or details via email, at mina.pecheux@gmail.com. I'd be happy to try and help! Cheers :)
Hi, thank you for the great tutorial video. But I have a problem, my player still moving while I release the key. It can be fixed by the setting velocity of rigidbody back to 0 in Idle state, but it isn't like what you do.
Hello - and thanks for the nice comment, I'm glad you liked the tutorial :) So I cannot be sure with just this info but the problem could be due to the setup of your Rigidbody... basically, the idea is that Rigidbodies accumulate velocity and then have to dissipate the energy by dragging on the ground. So if your drag isn't high enough, the velocity won't go back down to 0. If you want, you can also send me your project files via email (at mina.pecheux@gmail.com) - I can take a look and see if I can help :) Cheers!
@@quangchienngo453 You can do that if you want to force a full stop - I think it should not cause any issues with the physics :) Otherwise, if you want the player to slow down instead of stopping directly, you can also bring the friction up ;)
so is this usable for anything? like player, idle, move, attack, hit etc. and also enemy? like idling, patroulling(walking), detecting player, walk to player, attack player...? ^^
Heya! Yep I think it's a pattern that could apply to a lot of things :) For example, for a player, you wouldn't "auto-trigger" the transitions like here obviously, but you could have different states with their animations, or other rendering specificities (or even different modes like in a vehicle, etc.)! I've mostly used it for AIs in my own projects, but it's basically applicable to anything that can be modelled with separate states ;)
Can we create a List for our all states that derived from BaseStats Because we want to write and Initialize evert new created state we simply just drag our new state script in thar list how can we do this?
Hello! To do this, you might want to do an "auto-register" system. Basically, you define a static list in the BaseState class (let's say it's called "statesList": that will be your list of states), and then in the Start() method of this BaseState class, you add your current object (i.e. "this"). This way, whenever a new state is created, it will self-register in the list (cause don't forget that BaseState-derived objects should ultimately call this constructor too!) :) Then, you can access your list of states by calling "BaseState.statesList". Of course, if you destroy states at any point, you'll need to reupdate the list. Hope it helps, cheers! :)
Hello! First of all- thanks for the nice feedback, I'm happy you liked the tutorial :) And about your question: I've talked about it in the text version (linked in the description), here's just a copy-paste: "The FixedUpdate() is usually used for physics because it enforces a fixed time delta, i.e. all frames will have the same length, which is better for physics computations. However, here, we are going to focus on the Update() and LateUpdate() methods, because we want to make sure that we run things in the proper order. Note: even though we’ll compute physics, we don’t care so much about having a fixed delta time as we do about the state machine not getting lost in its transitions. That’s why I’d rather insure the sequencing is correct and I chose to go for the Update() and LastUpdate() entry points." For more info about Unity's built-ins execution order: docs.unity3d.com/Manual/ExecutionOrder.html Hope it helps, feel free to tell me if you have another question! ;)
Sorry for the late comment, does this work in Unity 3D as well? I tried these scripts in a 3D project i made but the player does not enter the idle state even with the GetInitialState scripts and setup identical
Heya! So you'll need to take a look at the differences between the Unity.Physics and Unity.Physics2D modules: there are equivalents for most of the functions, but a few things are different; and of course, you need to make sure all your components are consistent (i.e. 3D colliders go with 3D rigidbodies for example) :) Do you have any error in the console that may explain that your player "interrupts" early? Cheers!
Heya! So the idea was to enforce the proper sequencing of my different logics, and in particular to ensure that if I use the LateUpdate of a state, it is indeed executed after the Update of all others. Plus, here, I don't do very complex computations with the physics, so it should be alright. But you're absolutely right that we usually use FixedUpdate for the physics to get a fixed time delta and, in a real game, you'd probably need to examine your logic execution flow closely to use the right kind of update method (e.g. FixedUpdate) while maintaining the proper execution order. Hope it clears things out, cheers! :)
Hi! So you're absolutely right that, here, my base methods are pretty empty so we could make them abstract ;) I just wanted to explain the whole "calling the base method" thing for people who are less used to inheritance, so I preferred to make them virtual for the purpose of this tutorial. Basically, I didn't want viewers to feel "lost" if they wanted to add some shared behaviour in the BaseState, and only had abstract methods to play with. But yep - thanks for pointing this out: these could totally be made abstract ;) Cheers!
@@minapecheux Thanks for the clearance. It is true that inheritance is a bit tricky and a little bit confusing if not used to it. Great tutorials i really enjoy them.
As soon as there is a fixed update and the timing from the changestate is off, the action in fixed update are running infinite. Isnt there a way to run the fixed update 1 time/frame/tick after the change. i saw that other fsm had fixedupdate so how are they doing that. Or is this possible with an exit and wait 1 tick until the change of the state
Hello! Hmm... sorry I'm not exactly sure what your issue is :/ If you want do have some behaviour occur for just one tick, then you'd have to have an intermediary state - this would be the one you transition to, and then its logic would simply do the thing to do for one tick and then chain with another transition. But perhaps I misunderstood... If you want, feel free to add more details or send me an email (at mina.pecheux@gmail.com) with some info or even your project, if you think I can help ;) Cheers!
@@minapecheux Thank you very much for your effort, i meant how can you add fixed update without interfearing with the state change. I like to have physics in fixed update because in lateupdate it interfears with other code that i have written
@@rothm619 Ah ok, sorry, got it ^^ So as I explained in the written version (link in the description), the reason I use LateUpdate instead of FixedUpdate is because I want to properly schedule the various pieces of logic (= I want to make sure things are executed in the right order) and it was easiest/quickest to do it this way in the tutorial. (If you're not familiar with Unity's functions lifecycle and the ordering of Update, FixedUpdate and LateUpdate, you can check out the docs here ;) docs.unity3d.com/Manual/ExecutionOrder.html) But you can also work the logic a bit more in depth to avoid this kind of issues - basically, you just need to make sure that the actions play in the right order, but you can totally update the physics in the FixedUpdate() (as it "should" normally) to have it mix well with the rest of your systems :) (It's really specific to one project, though, so I can't really give you more pointers ^^) Hope it helps!
@@minapecheux To fix the problem, i call the fixed update 1 time in state change so that it can reconize that the button isnt pressed anymore, like this public void ChangeState(Base_State newState) { currentState.Exit(); currentState.FixedUpdateState(); currentState = newState; currentState.Enter(); }
Hello, Thanks so much for making this tutorial! I am a pretty inexperienced coder and I am working along with your tutorial, I ran into a problem with the line stateMachine.ChangeState(((MovementSM) stateMachine).movingState);, I'm getting an error that says "CS1501 C# No overload for method takes 1 arguments", do you have an idea what I've done wrong? Thanks again for the tutorial!
Hello, thanks, I'm really happy you like it! So: this error means that there is a mismatch between the number of expected arguments and the number of passed parameters for your function. In this case, you are calling ChangeState(), with one parameter: ((MovementSM) stateMachine).movingState. My guess is that you perhaps have a little error in the declaration of your ChangeState() function (in the StateMachine.cs file) and that it expects more or less than 1 argument (i.e. you have more or less than 1 thing inside the parentheses in its declaration) ;) Also: make sure you did write this line exactly like this - it's pretty easy to make a little mistake with the parentheses, and it could lead to you passing in more than 1 parameter by error... :) I hope it helps, cheers!
I do not get why all people in videos I saw do statemachines as monobehaviour. I do not recommend to make StateMachine as Monobehaviour. If you do OOP and you need to use other class as parent so statemachine wouldn't work then. For instance mirror or unitys new network system uses NetworkBehaviour. What then? Do this as normal class without any parents. And then create the instance in monobehaviour. I made like that and it is much better and you have more overview. For instance: --- AgentMovement.cs StateMachine stateMachine; Awake(): stateMachine = new StateMachine(this); // AgentMovement is monobehaviour stateMachine.Add(); // Add will add the state type to the list with new instance. stateMachine.Add(); ... etc Now if I want to change state I do just stateMachine.NextState(); "Add" "Get", "NextState" will return the instance so you can even change values of the states if needed (in most case you don't). For instance: stateMachine.NextState().targetPos = targetPos; in the states there are events like OnEnter or Update and will always have parameter "StateMachine" so you can use in the state also NextState. Since mono is also there I can access to monobehaviour in the states as well like targetPos = stateMachine.Monobehaviour.targetPos So I do not constructors or ugly : base() behind it. This is really annoying to write same thing on every knew state.
Hello! First of all, thanks for your interesting comment :) I find your approach valuable and I'm happy to mention it - in terms of why I did it with the "usual" MonoBehaviour setup, allow me to answer in several directions - hopefully it will make sense ^^: - from a "tutorial" point of view, it's slightly easier to do a MonoBehaviour and directly use the Start/Awake methods given by Unity, because it's what most Unity devs (or Unity enthusiasts) know - thus it makes it more straight-forward and helps focus on the FSM topic and its design ;) - in my own experience (perhaps it's different in your case), the state machine was the "highest" level of component on my entity, meaning that I didn't see any point in having a parent class to oversee its behaviour. I like scoping the behaviour to classes, and avoiding having too much entanglement between them (well, as little as possible anyways), and I feel like handling states/transitions in a parent class could quickly lead to "too many" globals (again, in my own opinion - I've never tried it so I might be missing something :D). - I think in most cases, for example with the NetworkBehaviour, the point is to tie the lifecycle of your entity (be it a single character with its FSM or the entire network state with the NetworkBehaviour) to the lifecycle of the scene with Start(), Update(), etc. Overall, I think it's mostly a question of preference. Your idea is definitely worth mentioning, especially because it's quite rare, so if it holds up to the "common" way, it can be a nice thing to have an alternative... Not sure how much it answers the question, but I hope it helps understand my point of view, at least! Cheers :)
Incredibly underrated tutorial! I've used this in my last two games and it's a total game changer, coding a state machine makes code so much cleaner and organized, and after expanding on it to also account for triggers and collisions, there are virtually no limitations. I've tried using the animator or enums to get similar behavior, but this is so much less convoluted as it isn't nearly as reliant on bools and if statements. The tutorial uses a player controller as an example but using this for enemy AI is also great! And I haven't even mentioned what this taught me about inheritance , thank you so much for this!
Thank you so much for your nice comment! I'm really happy you liked the tutorial and it helped you with your project :)
Yup, FSMs are a nice way of structuring "basic" AI behaviour, too!
@@minapecheux hi howeryou i wantto add a damaged state when enemy collide with bullet where i checht for collision?
@@Maskeowl Hi :)
So it depends on the exact architecture of your FSM, but basically: any state where the collision can occur should contain the collision check logic. For example, here, both the Idle and Moving states should probably handle the damage routine, so you'd need to include it in both states.
But if you have that sort of "global" behaviour that you want to share between multiple states, then you may want to look into hierarchical FSMs - and I've made another tutorial on those if you want, over here: ruclips.net/video/OtUKsjPWzO8/видео.html
Hope it helps,
cheers :)
@@minapecheux am i doin it wrong ? because i cant add onCollisionEnter void to states
so i did it at MovementSM it look like its working , also i saw that video thanks tho but i think i need a bunch more neuron and Iq to understand lol
@@Maskeowl Ah yes, the reason you can't add OnCollisionEnter to the state classes is because those are simply "pure" C# classes, but OnCollisionEnter only works inside a class that inherits from the Unity built-in MonoBehaviour class!
So indeed, you either have to catch the collision in the higher-level StateMachine-derived class (here, the MovementSM) and then warn the states, or not rely on the OnCollisionEnter :)
Your explanations clear and concise and your voice is super easy to listen to, fantastic tutorial
Thank you so much! I'm really glad you like it :)
I'm a year late, but glad I found this. Recently started game dev again and I was pulling my hair with all the if statement logic. Time to practice this. Best tutorial/explanation I've found! 😁
Many thanks! I'm glad you like the video and find it useful ;)
This was so helpful! I am making my first game in Unity after a while of working with Godot, so it was great to see how you can implement state machines in Unity. Thank you!
This is the type of tutorial that I was looking for, thank you so much for keeping finite state machines well explained and concise.
Thanks for your nice comment, I'm really happy you liked the video! :)
This is probably one of the most straight forward concepts I've seen of a FSM done in unity. Though I'm having trouble with implementing it with the new Unity Input System, I still understand just about everything that needs to be done. Your video on hierarchical SFMs also makes the prospect of them seem a lot less daunting to tackle!
Thank you so much for your nice feedback, I'm really happy you liked this video and I hope you'll like the next one, too! Cheers :)
Incredible tutorial! So simple and well explained, what a genius!!! Don't stop teaching like that 'cause you are great!
Thanks! I'm really happy you like it :)
Great Video. For so long I have search for an understandable solution implementing the FSM. Thanks a lot
You're very welcome, thanks for the nice feedback ;)
And happy I could help!
Wow, tbh I was worried that implementing an sm was going to be painful that I was almost considering not doing it, but you explained it so well and changed my mind. Thank you for this tutorial, it was very clean and to the point.
I'm glad it helped! Thanks for the nice comment :)
Hey! Thank you so much for this tutorial; as someone who has just started with unity and programming in general, this was really helpful and I was able to get my own state machine working for my project!
You're very welcome, I'm happy it helped!
Looked up many FSM tutorials before landing on this one. It's explained very clearly! Thanks for taking the time to put this together!
Thank you so much! I'm really happy you like it :)
j'ai adoré, je ne suis pas du tout dev et j'ai tout compris !!! merci beaucoup pour cette video !
Merci beaucoup pour ce gentil commentaire ! Contente que ça vous ai plu :)
Your voice is really good and the way to deliver is appreciatable
Thanks, really happy you like it!
Hello @Bertrand - for some reason, your comment doesn't show, sorry :/
What I do at 22:10 is that I use a public field I added to my MovementSM class (so in your case the PlayerControl class) called "movingState" and that allows me to reference my instance of the Moving class. It is not a cast ;)
So perhaps make sure you did define this field in your PlayerControl class as shown at 20:16?
Cheers! :)
Great & clear explanation about state machines. Learned a lot of things. Thank you
Thanks a lot for your nice comment, happy you like the video and found it useful!
Cheers :)
Amazing, straight-forward tutorial. Thanks so much.
Hello - and thanks a lot for your nice comment, I'm really glad you liked the tutorial! :)
Excellent presentation, you gained a subscriber. I am playing with a completely generic HFSM in C#/Unity based on Ian Millington's book AI for Games. In that implementation you don't create new classes for states, instead you pass the State class its actions for the entry, update and exit, as well as its transitions. Basically you inject the logic into the base class. More complicated to follow than this approach in the video (which seems to be the most common), but very flexible and elegant.
Hi, thanks for your really nice comment! :)
Yep, I've already worked with that sort of logic injection (although to be honest it was in Python so I didn't have to concern myself with declaring delegates ^^).
It's certainly a bit more complex but also more adaptive. In a sense, I feel like it's a first step on the path to data-driven logic definition (Bob Nystrom talks about here for example: gameprogrammingpatterns.com/bytecode.html), which is an absolute gem when done right! (especially in terms of including your designers every step of the dev, and not just spending months re-translating their ideas into code :D)
@@minapecheux I'll definitely have a look. Yes, delegates can be a bit of a pain and with the generic solution you still have the problem of storing or accessing variables from inside your states' actions, whereas with specialised state classes you can do what you want really, so I am still deciding what I want to use.
Man that is a good tutorial. I didnt understand this topic from other ytbers because the words where to complex for me as a german speeking person.
Thanks a lot for your nice comment!
I'm really glad you liked the video and found it useful :)
thanks alot, saved me so much effort and was real easy to follow
Thanks for your nice comment, I'm really happy you liked the tutorial! :)
Well done, Thanks for your effort.
thank you so much for this video. im using fsm for my school's project and this helped me understand it a lot better
hi! I'm really glad I could help, it's really cool if you got enough theory through this video :) good luck on your project!
Really loved it, Keep up to good work.
Thanks for the nice comment!
Hi @RammyRock - for some reason, your comment doesn't show, sorry :/
You're absolutely right when you say that we don't absolutely need the StateMachine reference in the BaseState class, since we "override" it with our typecast in the derived ones! It's just sort of a "habit" I have when writing my abstract FSM classes so that, if my derived FSMs don't typecast it, I still have an easy link to refer back to ;)
But you could totally optimize the code and memory management by removing this variable, in this case example!
Loved the tutorial! I might have some questions later on when I implement it haha.
Thanks a lot! I'm really glad you liked the video :)
Feel free to drop a comment or even send me an email if you have further questions - no problems!
Cheers ;)
Hello there! So @reendevelops for some weird reason your comment is not showing, I'm sorry, I'm not clear on all the YT moderation rules... but anyway ^^
About your 2 questions:
1. "Can I use this StateMachine for NPC/Monster behaviours?"
Absolutely! Here, I'm using user inputs to switch between states, so I get a "Player" state machine, but you could totally have other algorithms and a different logic to automatically switch between states, which would make an AI.
For example, instead of waiting for a key to be pressed to toggle to the "moving" state, you could instead look for nearby game objects with a "Player" tag and if they're close enough, move towards them. This would create sort of a "chase" behaviour for your NPC.
2. "If I also use this on my Player, can I add states during runtime? For example, if the player obtains a skill like Dash, would it be possible?"
I would recommend keeping the structure of your state machine the same, but locking some transitions at the beginning. So, all your states (the "dash" included) would exist upfront, but first you won't have some boolean flag somewhere saying "canDash = false;". And in your transition to the "dash" state, you first check this flag and abort everything if it false.
Then, when your player unlocks the "dash" state, you'll just turn this flag to true and all your transitions will already be ready to play!
Hope it's clear :)
Cheers!
@@minapecheux Ahh, that would be it. So I'll set up all the possible States in the beginning and just unlock them with a transition along the way.
That makes sense. Thank you so much!
I'm at the point where I've seen enough FSM tutorials to completely understand how they work.
So I'm mostly looking for the tutorial with the cleanest code to copy for the base class.
And I think this might be the one!
Thank you, I'm really happy you like the video/code ;)
This is so useful. Merci.
You're very welcome, thanks for the nice comment! :)
This needs to be sponsored by Unity.
So, I was wondering is there some good methodology to pass information from one state to another state like an object for example ? Thank you !
I've personally tried two different things:
- using the parent FSM manager to have a global data context (but in that case you need to remember to pass this parent object to the state instances :) )
- using a global event manager to completely decouple the states - if you're curious, I've actually made a tutorial on the topic a while ago: ruclips.net/video/EvqdcyTgZNg/видео.html
Great explanation, but I still got question. Is it legal that each state has ability to change StateMachine as a class (changing its current state), when StateMachine itself can do nothing about it? I mean, SOLID tell us that each class must take responsibility for but himself, though in case of FSM it seems to be exactly opposite. That's also lead to a problem that StateMachine class is extremely opened with those public fields inside it, which seems as encapsulation violation. Am I getting something wrong or it's just specifics of FSM pattern?
Hi! I'm happy you liked the tutorial, and thanks for your interesting question :)
Yep, that's actually one of the reasons why state machines are "coupled" patterns - because of how they are structured, the only one that knows when to transition to another state... is the state itself, not the machine! Basically by nicely separating the logic of each state in a class, you also force this state to be responsible for all outgoing transitions, since none of the other components in the system know what's going on.
Note that to protect your StateMachine fields, you can go from public variables to getters-only with C# properties: this makes them readonly, which can be useful for the dev phase. But it also makes the access a tiny bit slower, so usually, you revert back to public variables in your builds if you want the execution to be as quick as possible ;)
I hope it helps,
feel free to ask more questions,
cheers!
A useful tutorial, thanks. :) I don't know whether I'm missing something, but I just want to ask about the part where you call a function from the parent class, for example:
public override void Enter()
{
base.Enter();
sm.spriteRenderer.color = Color.black;
_horizontalInput = 0f;
}
I got confused because I assumed that Enter() function in the parent class has not been defined. Greatly appreciate the help :)
Hi! I'm happy the tutorial is helpful ;)
So the functions are defined in the parent class, although they are empty! That's the cool thing with virtual functions: you can define them with or without prototype in the parent class, and then partially or completely override it in the children.
That being said, it's true that here, calling the parent functions is useless^^ it was just a way for me to show people who are a bit new to inheritance how to do this if they decide to add logic in the parent, and want to keep it in the children :)
Hope it answers your question,
Cheers!
@@minapecheux thanks :)
I always wanted to use state machines but it is a lot of extra work and I'm not sure if it is worth for complex controllers that have many states that can overlap and depends on each other, I would rather adding 3 extra checks and not adding 10 extra script that will create a web
Question here! Why does each state have to do base.Enter() / base.UpdateLogic() and such when the base functions themselves are just empty? I thought the point of override functions were so you can just conduct that function inherently, and the only reason you would do base.(corresponding parent function) is so it also conducts the code in the base class's function?
Hello! :)
So you have to be careful about one thing: the base function is only called automatically for constructors/destructors ;)
Meaning that here, for example: if I override the Enter() function in my Node-derived class, it will only execute the code inside the override, and not the base code! To have both the base code and the overriding one, you need to explicitly call the base function, using base.Enter().
Override functions are a way of specifying the "default"/fallback behaviour declared in the virtual function, but it does not necessarily imply executing such behaviour... so it's actually better that it doesn't do this automatically!
(Note that, on the other hand, if I don't write any override at all matching a virtual function in my base class, then it's that virtual function's logic that will get executed)
Hope it helps :)
Cheers!
@@minapecheux Hello! I understood that part, but my confusion is why you called the base function in your code when the base.Enter() function is EMPTY?
@@arkhtyi9456 Oops sorry - I read too fast ^^
Yup you're absolutely right that here the functions are empty so we could remove this :)
Honestly, it was just a way of introducing this mechanic in the tutorial and teaching people about this specific thing (especially if you decide to add some shared logic in the base.Enter() function, be it for debug or actual runtime effects, then you know how to keep it even with the overrides) ;)
But thanks for pointing this out - cheers!
@@minapecheux Thank you for the fast and kind reply despite being an almost 2 year old video! I was just worried maybe I was missing something like you still have to do the base function for some inheretence, code invoking magic reason :)
Your Tuto was a Great Help for me, I'm willing to add some buttons instead of keyboard, Do You Have any Advice Where To put a method to detect a Button Click event , in the moving script which requires adding a gameobject or the or The MovementSM ?
Thanks, I'm glad you liked it! :)
I guess in your case I'd make some global event system, so that I can click on a button and have this click send a "move left" event (for example). Then, I'd add a listener in the Idle class, so that I can transition to Moving. You might also need your event to have some extra data about the direction you want to move towards, but here I'll let you organise it as you want ^^
Then you should probably have a "on button release" -> "stop" event chain, to go back from Moving to Idle.
By the way, if you're curious about this global event system thing in Unity, I made a tutorial on that topic :)
ruclips.net/video/EvqdcyTgZNg/видео.html
Hope it helps,
cheers!
@@minapecheux Thank You
Really nice. As it progressed it felt it was more like a hierarchical SM. Idk, I’m not very experienced. What is the difference between them?
Thanks! Well, actually, this video is a "prequel"/first part, directly followed by a second one on the hierarchical FSMs, over here: ruclips.net/video/OtUKsjPWzO8/видео.html
So good catch ;)
Hi, nice video to tell about FSM, but i have some issue here, in the state like idle and moving we casting the MovingSM, how we can change that behavior for let say 5 NPC with difference type?
Hi, and thanks for your nice feedback!
So basically if you want to have different behaviours, you'll probably need to create one StateMachine-derived class for each, and for your State-derived classes you'll also need to:
- use some data/variables to specialise the instance (e.g. your state's class constructor could receive the name of the animation to load, and so you can use the same class for two NPCs with different animations, just by providing a different name in the constructor)
- or make different scripts if it's really too specific to each ;)
I hope it's clear, tell me if you want more info!
Cheers :)
@@minapecheux Thanks for the reply, can i send u my code so i can easily tell u what i wanna make Mina?
@@dickydarmawan427 Hi again - sure, feel free to share our code via email, at mina.pecheux@gmail.com.
Cheers :)
Thank you
ty for video, more unity tutorials
I've been following this tutorial for a game I'm working on, but I've hit a road block. At 17:15 how do I get the input from Unity's "new" input system?
Hi! I think this page from the official docs should contain all the required migration tips for converting this code to the new input system: docs.unity3d.com/Packages/com.unity.inputsystem@1.7/manual/Migration.html
Hope it helps,
cheers! :)
@@minapecheux I think I've found the solution, thanks!
Thank you!
Great tutorial!
Thanks, I'm really happy you like it! :)
Hey! I'm not sure if you will be able to help me or not, but I am implementing this state machine in a small game I am working on but I am having a slight issue. When switching between states, it is changing the value of some of my variables, even though there is zero logic on the transitions that could cause these values to change. The values that are being changed are held in my 'MovementSM' script and I am referencing and changing them from the specific state scripts. Is this the wrong way to do things? If I have been too vague about my issue, I can elaborate further
Either way this tutorial and a few others of yours, have been super helpful! Thanks a ton!
First of, thanks a lot for your nice feedback, I'm really glad you liked the tutorials :)
About your question:
- if you have "global" variables that should be cross-states and impact your entity at a higher level, then it makes sense to store them outside the states; you can put them either inside the MovementSM (if they are roughly linked to movement, like the "speed" in my example), or even in another PlayerManager script for example and then access it... basically it depends on your project structure ;)
- not sure why your values are changing though... it's a bit hard to tell you out of the blue and without the code, sorry ^^
If you want, you can send me your scripts and/or details via email, at mina.pecheux@gmail.com.
I'd be happy to try and help!
Cheers :)
Hi, thank you for the great tutorial video.
But I have a problem, my player still moving while I release the key. It can be fixed by the setting velocity of rigidbody back to 0 in Idle state, but it isn't like what you do.
Hello - and thanks for the nice comment, I'm glad you liked the tutorial :)
So I cannot be sure with just this info but the problem could be due to the setup of your Rigidbody... basically, the idea is that Rigidbodies accumulate velocity and then have to dissipate the energy by dragging on the ground. So if your drag isn't high enough, the velocity won't go back down to 0.
If you want, you can also send me your project files via email (at mina.pecheux@gmail.com) - I can take a look and see if I can help :)
Cheers!
Oh, I figure it out. My player has no friction. So is it ok if I set the speed back to 0 in Idle State?
@@quangchienngo453 You can do that if you want to force a full stop - I think it should not cause any issues with the physics :)
Otherwise, if you want the player to slow down instead of stopping directly, you can also bring the friction up ;)
@@minapecheux Thank you so much for the video and the replies :)
@@quangchienngo453 You're welcome, happy I could help!
so is this usable for anything? like player, idle, move, attack, hit etc. and also enemy? like idling, patroulling(walking), detecting player, walk to player, attack player...? ^^
Heya! Yep I think it's a pattern that could apply to a lot of things :)
For example, for a player, you wouldn't "auto-trigger" the transitions like here obviously, but you could have different states with their animations, or other rendering specificities (or even different modes like in a vehicle, etc.)!
I've mostly used it for AIs in my own projects, but it's basically applicable to anything that can be modelled with separate states ;)
Can we create a List for our all states that derived from BaseStats
Because we want to write and Initialize evert new created state we simply just drag our new state script in thar list
how can we do this?
Hello!
To do this, you might want to do an "auto-register" system. Basically, you define a static list in the BaseState class (let's say it's called "statesList": that will be your list of states), and then in the Start() method of this BaseState class, you add your current object (i.e. "this").
This way, whenever a new state is created, it will self-register in the list (cause don't forget that BaseState-derived objects should ultimately call this constructor too!) :)
Then, you can access your list of states by calling "BaseState.statesList".
Of course, if you destroy states at any point, you'll need to reupdate the list.
Hope it helps,
cheers! :)
@@minapecheuxok I"ll work on this and also shares with you if I found any valuable solution for this
Thanks for your reply
Someone know why she uses LateUpdate for UpdathePhysics? It's not FixedUpdate the correct one for the physics?
PD: Perfect tutorial!😄
Hello!
First of all- thanks for the nice feedback, I'm happy you liked the tutorial :)
And about your question: I've talked about it in the text version (linked in the description), here's just a copy-paste:
"The FixedUpdate() is usually used for physics because it enforces a fixed time delta, i.e. all frames will have the same length, which is better for physics computations. However, here, we are going to focus on the Update() and LateUpdate() methods, because we want to make sure that we run things in the proper order.
Note: even though we’ll compute physics, we don’t care so much about having a fixed delta time as we do about the state machine not getting lost in its transitions. That’s why I’d rather insure the sequencing is correct and I chose to go for the Update() and LastUpdate() entry points."
For more info about Unity's built-ins execution order: docs.unity3d.com/Manual/ExecutionOrder.html
Hope it helps, feel free to tell me if you have another question! ;)
Sorry for the late comment, does this work in Unity 3D as well? I tried these scripts in a 3D project i made but the player does not enter the idle state even with the GetInitialState scripts and setup identical
Heya!
So you'll need to take a look at the differences between the Unity.Physics and Unity.Physics2D modules: there are equivalents for most of the functions, but a few things are different; and of course, you need to make sure all your components are consistent (i.e. 3D colliders go with 3D rigidbodies for example) :)
Do you have any error in the console that may explain that your player "interrupts" early?
Cheers!
amazing tutorial thank you
fast pace but super detailed n no b*llshit
Thanks! :)
Why are you using LateUpdate and not FixedUpdate for physics?
Heya! So the idea was to enforce the proper sequencing of my different logics, and in particular to ensure that if I use the LateUpdate of a state, it is indeed executed after the Update of all others. Plus, here, I don't do very complex computations with the physics, so it should be alright.
But you're absolutely right that we usually use FixedUpdate for the physics to get a fixed time delta and, in a real game, you'd probably need to examine your logic execution flow closely to use the right kind of update method (e.g. FixedUpdate) while maintaining the proper execution order.
Hope it clears things out,
cheers! :)
Hello mina i've seen that you use a lot of virtual methods that contain not very usefull code, why are you not making them abstract?
Hi! So you're absolutely right that, here, my base methods are pretty empty so we could make them abstract ;)
I just wanted to explain the whole "calling the base method" thing for people who are less used to inheritance, so I preferred to make them virtual for the purpose of this tutorial. Basically, I didn't want viewers to feel "lost" if they wanted to add some shared behaviour in the BaseState, and only had abstract methods to play with.
But yep - thanks for pointing this out: these could totally be made abstract ;)
Cheers!
@@minapecheux Thanks for the clearance. It is true that inheritance is a bit tricky and a little bit confusing if not used to it.
Great tutorials i really enjoy them.
@@bocdagla Thanks, I'm really happy you like it! :)
That whats I am looking for. It is simple and clear but the pattern itself confused me.
I'm happy you liked the video, thanks for the nice comment :)
As soon as there is a fixed update and the timing from the changestate is off, the action in fixed update are running infinite. Isnt there a way to run the fixed update 1 time/frame/tick after the change. i saw that other fsm had fixedupdate so how are they doing that. Or is this possible with an exit and wait 1 tick until the change of the state
Hello! Hmm... sorry I'm not exactly sure what your issue is :/
If you want do have some behaviour occur for just one tick, then you'd have to have an intermediary state - this would be the one you transition to, and then its logic would simply do the thing to do for one tick and then chain with another transition.
But perhaps I misunderstood...
If you want, feel free to add more details or send me an email (at mina.pecheux@gmail.com) with some info or even your project, if you think I can help ;)
Cheers!
@@minapecheux Thank you very much for your effort, i meant how can you add fixed update without interfearing with the state change. I like to have physics in fixed update because in lateupdate it interfears with other code that i have written
@@rothm619 Ah ok, sorry, got it ^^
So as I explained in the written version (link in the description), the reason I use LateUpdate instead of FixedUpdate is because I want to properly schedule the various pieces of logic (= I want to make sure things are executed in the right order) and it was easiest/quickest to do it this way in the tutorial.
(If you're not familiar with Unity's functions lifecycle and the ordering of Update, FixedUpdate and LateUpdate, you can check out the docs here ;) docs.unity3d.com/Manual/ExecutionOrder.html)
But you can also work the logic a bit more in depth to avoid this kind of issues - basically, you just need to make sure that the actions play in the right order, but you can totally update the physics in the FixedUpdate() (as it "should" normally) to have it mix well with the rest of your systems :)
(It's really specific to one project, though, so I can't really give you more pointers ^^)
Hope it helps!
@@minapecheux Thanks!
@@minapecheux To fix the problem, i call the fixed update 1 time in state change so that it can reconize that the button isnt pressed anymore, like this
public void ChangeState(Base_State newState)
{
currentState.Exit();
currentState.FixedUpdateState();
currentState = newState;
currentState.Enter();
}
🙏
Hello, Thanks so much for making this tutorial!
I am a pretty inexperienced coder and I am working along with your tutorial, I ran into a problem with the line stateMachine.ChangeState(((MovementSM) stateMachine).movingState);, I'm getting an error that says "CS1501 C# No overload for method takes 1 arguments", do you have an idea what I've done wrong?
Thanks again for the tutorial!
Never mind, I solved that issue! I forgot to write (BaseState new state) inside the parenthesis after ChangeState in The state machine script.
Hello, thanks, I'm really happy you like it!
So: this error means that there is a mismatch between the number of expected arguments and the number of passed parameters for your function. In this case, you are calling ChangeState(), with one parameter: ((MovementSM) stateMachine).movingState.
My guess is that you perhaps have a little error in the declaration of your ChangeState() function (in the StateMachine.cs file) and that it expects more or less than 1 argument (i.e. you have more or less than 1 thing inside the parentheses in its declaration) ;)
Also: make sure you did write this line exactly like this - it's pretty easy to make a little mistake with the parentheses, and it could lead to you passing in more than 1 parameter by error... :)
I hope it helps,
cheers!
I do not get why all people in videos I saw do statemachines as monobehaviour.
I do not recommend to make StateMachine as Monobehaviour. If you do OOP and you need to use other class as parent so statemachine wouldn't work then. For instance mirror or unitys new network system uses NetworkBehaviour. What then?
Do this as normal class without any parents. And then create the instance in monobehaviour. I made like that and it is much better and you have more overview. For instance:
--- AgentMovement.cs
StateMachine stateMachine;
Awake():
stateMachine = new StateMachine(this); // AgentMovement is monobehaviour
stateMachine.Add(); // Add will add the state type to the list with new instance.
stateMachine.Add();
... etc
Now if I want to change state I do just stateMachine.NextState();
"Add" "Get", "NextState" will return the instance so you can even change values of the states if needed (in most case you don't).
For instance: stateMachine.NextState().targetPos = targetPos;
in the states there are events like OnEnter or Update and will always have parameter "StateMachine" so you can use in the state also NextState.
Since mono is also there I can access to monobehaviour in the states as well like targetPos = stateMachine.Monobehaviour.targetPos
So I do not constructors or ugly : base() behind it. This is really annoying to write same thing on every knew state.
Hello! First of all, thanks for your interesting comment :)
I find your approach valuable and I'm happy to mention it - in terms of why I did it with the "usual" MonoBehaviour setup, allow me to answer in several directions - hopefully it will make sense ^^:
- from a "tutorial" point of view, it's slightly easier to do a MonoBehaviour and directly use the Start/Awake methods given by Unity, because it's what most Unity devs (or Unity enthusiasts) know - thus it makes it more straight-forward and helps focus on the FSM topic and its design ;)
- in my own experience (perhaps it's different in your case), the state machine was the "highest" level of component on my entity, meaning that I didn't see any point in having a parent class to oversee its behaviour. I like scoping the behaviour to classes, and avoiding having too much entanglement between them (well, as little as possible anyways), and I feel like handling states/transitions in a parent class could quickly lead to "too many" globals (again, in my own opinion - I've never tried it so I might be missing something :D).
- I think in most cases, for example with the NetworkBehaviour, the point is to tie the lifecycle of your entity (be it a single character with its FSM or the entire network state with the NetworkBehaviour) to the lifecycle of the scene with Start(), Update(), etc.
Overall, I think it's mostly a question of preference. Your idea is definitely worth mentioning, especially because it's quite rare, so if it holds up to the "common" way, it can be a nice thing to have an alternative...
Not sure how much it answers the question, but I hope it helps understand my point of view, at least!
Cheers :)