It took me a frustratingly long time to grasp state machines, but your first video on those helped me immensly. Having worked with them now for a while by now, this comes at the perfect time to think and tool with it a bit more :D!
Some points I'd make on State Machine design, since I'm quite passionate about those: - Avoid the term "Manager" unless the system is intended to be used once in a game scene. FSMs are very frequently used in character behaviour systems to control decisions, actions, animations, sounds and so on. Those are per-entity usages. Why not just call a spade a spade. It's the state machine that handles the states, regadless of whether it's one instance or a 100 instances in a scene. No better name than just "StateMachine" imo. - Use Message Passing. Anytime the current state or an external system wants to trigger a next state, store it in the SM in a private field instead of having the SM specifically asking the current state "hey do you have a next state for me?". Use a "private EState queuedState;" field instead. - There's high value in talking about the differences between a SM that internally decides when to switch states, or one that expects external systems to switch. Is there deliberate intention behind the transition method being public? This allows state transitions as a direct call from external systems, instead of handling that in the SMs own Update (see the previous point). - The dictionary approach severly restricts how State instances must be made. For one, they must be registered for every FSM when the FSM is initialized. Secondly, that also means they must be pre-defined which prevents dynamic adjustments to the state members. Thirdly, it expects a one-to-one mapping. This means a Walk vs Run state needs two separate enum values despite all the code behaviour being the exact same, only with the speed being the difference. Now imagine having a "slowedWalk", "boostedRun", "Sprint" and other variations. All of those could instead just be done during state construction, i.e.: "stateMachine.QueueNextState(new MoveState(moveSpeed))" where the moveSpeed could stay very dynamic throughout the game. There are other ways of passing movement speed but I think it serves as an example of flexible design. - Show an implementation of the initialization of these classes, in practical examples. How is the dictionary populated, how is the first state going to be set. Should the SM assume that there is such a thing as a "default" state. Should the SM allow having no state at all in some cases? - Flexibility in decision making. If a state needs to tell the SM what the next state is, it means that this state will act the same in most cases. Of course there can be some logic as to what state should be picked, but imagine using state for the character behaviour in an action game. If a state is to move to a location, how does the movement know what comes next? Should the character swing a sword or try open a door? A move state wouldn't know the answer without a lot of complexity that doesn't concern how movement is done (which contradicts SOLID principles). So if the movement completes, how should the next state be chosen. This ties into the use of a "default state" but also the thought about "external state decisions". This is also the biggest difference between a mere FSM and a fully fledged BehaviourTree. Although I would recommend a combination of the two.
"Anytime the current state or an external system wants to trigger a next state, store it in the SM in a private field instead of having the SM specifically asking the current state..." Is this because it's better for states not to have references to other states? Or that a state should be dealing with it's own logic and not worrying about what needs to come next?
@@notadev9000 It's for the other systems to "leave a message" for the SM so that the SM holds the needed info about the next state internally until it's the correct time of the update cycle to perform the switch. You can design a SM such that it depends on current state to provide necessary state on demand, but that comes with less flexibility and potential pitfalls. For starters, the code to provide the next state on demand might be decided during the states update loop, but the state would then need to remember this until prompted by the SM to provide it, which could be the next update. Secondly, this code would likely be produced by developers using the SM you made, and you want to make the system as robust as possible when it comes to user-extended code. I.e. it's preferable to internalize expected behavior into the base classes when possible. It's easier for the user to decide the next state to run while in the hot spot of the update, rather than "recalling" that decision when the SM says it's time. Thirdly, if the SM should be open to accept external systems requests to queue a next state, then that has to be done in a different way than prompting the current state, in which case, the alternative is a solution that works for both internal and external state changes.
@kennethkrist can you maybe share link for gist with your example of state machine? What you wrote seems correct but I am having trouble wrapping my head around it 😅
It is very uncommon for GameDev videos to get as deep and accurate in the OOP concepts and patterns. Most Game Dev videos focus on "make it work", you focused on "make it ELEGANT". Plus, the implementation is perfectly balanced between simplicity and reusability. Great work !
Even tho I knew these things already I still watched the whole thing cause it's so well edited and well explained, appreciate your work a lot man keep it up!
I loved your older tutorial about state machines. Right now, your type of implementation is what I commonly use, with some tweaks! I just opened TH-cam because I want to see other state machine's implementations and KABOOM! You are here. Amazing, as always a very nice video. Keep on!
After about a week of frustration trying to wrap my head around it, I've finally managed to use this and your last couple of state machine videos to create a reuseable heirarchical state machine 🎉 Now to implement it as a character controller using event based state changes 😅 Thanks for the fantastic tutorials!
8:40 Update is called on the mainthread, there is no parallelization happening. As long as no ExitState or EnterState method calls "TransitionToState" there is no need for "IsTransitioningState". Update is also only called Once per frame. Also, I find the design questioning that your state decides the following state. The state should not depend on other states at all, keeping it modular and interchangeable. the transitions should be defined on the state machine (or state manager) - imho. There might be applications for changing this, but I'm referring to a general purpose state machine
Hello! You are correct - others have pointed that out and it’s my mistake. I’ll likely correct it in a future video. As for the second point, that’s understood and reasonable, but I would say there are benefits to both the state manager deciding the conditions for transitioning or this implementation where the states do. In the future, I’ll probably make a video where the state manager handles it, as well.
@@headecas All unity methods are called on the main thread (including FixedUpdate). Parallelization only happens in unity when you explicitly implement it for a method (Like when using Unity's Jobs system).
State deciding on the following state is useful when you have a lot of states and need to keep the state machine free from bloat. Then again, I suppose you're suggesting the state machine calls the transition method on the current state and passes the next state, or something like that?
One of my main languages in c# (enterprise stuff) and this was nice and clean. well done. doing my own game atm. your doing well on these resources! Better than the usual throw code together approach from a lot on youtube.
State Pattern is really powerful and I used it in computer science all the time (since computers are state machines, do'h). But I think the subscriber pattern is the most powerful, since you get rid of polling which can be really taxing on your performance.
Since this was insanely helpful when I was using Unity, I'm coming back to use this as reference for implementing this into Godot 4. Easily the best explanation of State Machines
Thank you so much for sharing this with us. As a hobbyist gamedev I admit this is still beyond my complete comprehension but I am much closer to fully understanding it. Your video was very well put together and I'm sure I'll be referencing it in the future.
It's also useful to have a method to reset the state when the transition is happening (although that can just be inserted into the Exit method, I just find it cleaner to have a separate method for it). That is for when states are reused and not recreated (for example to avoid garbage allocation - it's a microoptimization for performance since on devices like mobile, a run of the garbage collector can actually cause some microstuttering - also tied into that: Dictionaries with enum keys will generate garbage as well. A workaround would be to a dictionary that maps from int to the state. This is a bit less type safe though). Another interesting implementation I've seen is to not deal with Enums, but with the "Type" type directly as dictionary key type. Then there are possibly some other design decisions people can make for themselves: Should the state machine manager check for a changed state itself, like here, or should each state trigger the Transition method directly. Is it allowed to transition from a type of state to the same type, or not? (most often, it is probably not necessary) What might also be useful is some sort of shared data container to store state in, so that states can cross access this. Such a container could be created by the state machine, or passed into the state machine, and then passed on to each state (for example through the state constructor).
Hey thanks for the detailed response. Can you provide an example of the "Type" type -- I have not seen that before but one other community member mentioned it?
@@iHeartGameDev from the top of my head - you could have a dictionary of type Dictionary or Dictionary and then initialize the dictionary with the types of available states for keys and their respective instances as value, either manually or with reflection (e.g. with Activator.CreateInstance(..)). Then, if the SetState in the state machine class is called, it can take a parameter of "System.Type", then will check if the respective key is available in the dictionary, and if so, switch to that state. (stateManager.SetState(typeof(CharacterStates.SprintState)); Sometimes my BasteState class also just uses virtual methods with an empty method body instead of abstract methods, so that the actual state implementations don't have to implement all methods, if they don't need specific logic for it (for example some states might not care about trigger interactions)
Thank you, this was really helpful! Just in time for my next game jam. I had been looking for a way to refactor my overly complicated state machine mess, and this was it! It integrates perfectly with my current system
Great video! I've seen some comments suggesting that statemachine should control when states change, i would say it highly depends on use cases. If you have need for more dynamic statemachine like a hybrid of behaviour tree than yes, this is trouble, but i can see a lot of use cases when this implementation will save statemachine to be bloated and delegate functionality to states themselves. Cool stuff!
Thanks so much for watching and for the kind words and insight! Everything is contextual in programming imo… there are certainly best practices but even those have multiple avenues and competitors as to how something can be done. Well said!
It might be useful to include variants of this implementation such as utilising a stack in your FSM brain to return to a base state after completion. This would help for menus, states like attack follow-up/combinations and may not be immediately obvious for a fresh game developer.
@@iHeartGameDev Personally, as someone who is learning, I really like the longer videos. There is no shortage of short tutorials, and usually those don't even scratch the surface of more complex topics such as this. But I do understand that you also make them with engagement in mind. Either way, I appreciate you taking the time out to make this series!
Oh, that's cool! I always wondered when to use a stack and this seems like the perfect usage. Would be perfect for the turn-based game I'm working on. So, you'd do something like: In your attack menu, add the attack menu state to the stack. Then once you pick the attack, you slap that bad boy onto the stack too. Then whatever your attack does gets slapped on there, such as a targeting menu, cinematic, and what have you. Is that more or less correct?
@@noctisocculta4820 A stack is first-in, last-out so it's great for when you need to 'unwind' back to a state once something is complete. Taking your menu example, the UI would open your initial list of options. Let's say we hit attack. The attack menu opens up. We now see a list of special attacks we can do. We select one. Now it pops up a list of targets on the UI. We select one and off it goes! Each of those UI panels are a state. But they are only there until we select an option. After we've done all the selecting or we change our mind, we want to unwind and drop all those states to return back to the previous state or clear the states so the base can handle finishing up. We cannot continue to pop things on the stack indefinitely. It's power in this use case comes from being to stash the context of previous states despite being in the 'next' state, allowing us to unwind the stack quickly and easily.
@@_KB88 Thanks for the reply! Awesome, so my example would work the way I thought it might. Every time I've made a system it always gets super complicated, and I give up under its weight - thanks to you, I think I can make a lightweight, readable system that can be extended without cognitive overwhelm/ refactoring. Cheers, mate.
Hey man I really really like your videos. I have struggled quite a lot with state machines, yet i`m still struggling with some stuff but you are making it really easy for everyone to understand. I generally got a good idea how do state machine works, yet I still lack some understanding how to implement movement controls (as for fps character). So, I would like to ask you, if possible, maybe in a future video to show us an example of FSM of a FPS controller (based on a rigid body movement) and the new unity input system (which is based on input events). I assume since it's really hard for me to grasp all the aspects of it, that there are lot of people having the same troubles. Thank you for all the good tutorials so far!!!
Awesome tutorial as always, learned about state machines in your previous videos on the topic! :) However I would appreciate a few minutes of how to use it, create concrete states, add them to dictionary - actual usage. I find it a bit confusing to get started with this! Anyhow, great video, awesome editing etc! Keep up the good work ,you rock!!
Thank you Steven! My next video is a practical example of how to set up a state machine with this base implementation. It will be for the procedural animation series though instead of 3rd person character controller. Hopefully the walkthrough is enough to get an understanding for you
Hi, i just wanna let you know that i learnt various state machine and i think yours is best for me as a beginner. I implemented a similar state machine in my ebook and specifically mention your TH-cam channel. The book title is How I get tricked by Unity and it is on amazon now. Please there is no need to buy or advertise. I get only penny out of this book and i just try to share how beginners like me can code in Unity. I put your link on page 519. If you wish to have a look, please feel free to drop me a note and i can print screen. Anyway, thank you very much for your sharing! Keep up your good work. Flamming
I am confused as to where the logic for these states go. I made a few classes inheriting from BaseState e.g "public class IdleState : BaseState"... I haven't been able to figure out how to use the enum to get this state though. I wonder if maybe I have completely misunderstood the idea here.
Great video. Very informative and well presented. I think there are some improvements that you could make. In the Update, you should short circuit if "isTransitioningState" is true before you call "GetNextState()" so that it doesn't get called every frame. IMO, it's more readable as well. You can see at a glance which conditions will cause subsequent logic to skip. When building abstract classes I think it's important to be as performant as possible. Instead of an update that constantly checks whether the state changes, it would be better to implement an event driven solution. That's probably outside of the scope for this video, though. Overall, great tutorial!
Very nice pattern! Thank you so much for sharing. My two cents about it: making the methods of BaseState 'virtual' instead of abstract would allow not to implement them if not needed, leading to less clutter in the implemented states.
Any plans on potentially expand on this and explain how to incorporate support for substates? And as many others have pointed out, event-based statechanges and such would be very appreciated! That said, fantastic video. I'm trying to learn more about FSM's so this was great. :)
You're the second to ask about it, and I do love hierarchical state machines so I'll definitely add it to my list of content to cover in the near future. And I've also gathered that the event-based state change is recommended by a bunch of people, which I'm happy to take a look into!
Moving to Godot but as great part of your explanations are engine agnostic or can be tried out without much hassle I'll keep following you, thanks for this superb video!
Hey, I remember recommending using the dictionary to cache your states way back then. Now here you are, teaching me a new and clean way to reuse state machines! I love how that works. I am curious, why are you handling state swapping the way you are? From what I can see, you're taking the indirect approach of having the states return their own keys when asked for the next state key in GetNextState. Wouldn't it be easier to put the responsibility on the states themselves to call the TransitionToState(State stateKey)? As I'm typing this, I realize that by having the states return the next state with a method call, you don't have to cache the state manager! Thats clever, very clever. I find myself bogged down not only by repeatedly making state machines, I always have extra code for keeping that reference in the states. You've taught me two things today!
:) I remember your recommendation! I’m happy to see you return! There are definitely still improvements that I can make. Looks like this won’t be the last state machine video I make!
I believe it's necessary in multi-threaded scenarios and if there are asynchronous operations that could potentially interfere with the state transitions. Your point is valid though -- it might be redundant at the moment!
I admire your perseverance. You are obviously very passionate about some coding patterns (like State Machines lol) and you try to teach them to the Unity community, which is dominated by beginner level coders trying to "make a game" and quitting after it gets serious. Even though the reception of such more intermediate level lessons is not as good as of the standard "flashy FPS game unity tutorial" you don't let yourself get drifted towards the easy market. And for that I wanted to say thanks!
Something I would like to see discussed is when to split certain behaviors between multiple state machines vs creating an often complicated hierarchy within a single state machine. I would always get tripped up by whether to keep a player’s traversal state (walk, run, idle) separate from a combat state (attacking, guarding etc.). In summary: when should an SM be split into multiple SMs even if the behaviors interact with each other? (Ex: can only perform certain attack when in x state etc)
In summary: when should an SM be split into multiple SMs even if the behaviors interact with each other? (Ex: can only perform certain attack when in x state etc) But doing so complicates the problem, we can try the ability to switch when combining a number of keys into a set of states or a certain key to exit a certain state and have a flexible transition.
Great video! However, I don't quite understand why we need to check for IsTransitioningState. Following this implementation, Update() is a synchronous method and therefore all of the code (of this and every other Update() method) is executed before the next Update() is invoked. Therefore, there cannot be multiple state transitions at the same time. Even with event-based state transitions, I don't see why we need to check this, as the events should be handled in sequence and not in parallel. Am I wrong?
Another community member pointed this out! I believe it's necessary in multi-threaded scenarios and if there are asynchronous operations that could potentially interfere with the state transitions. Your point is valid though -- it might be redundant at the moment!
we could add a “transitioning state” if we want the “one frame transition” behaviour (eg Hidden, Appearing, Appeared, Hiding). or with this implementation, we only have two states (Hidden, Appeared) but allow the transition to happen across few frames.
@@iHeartGameDev the explanation about how "different framerate can make the function be called multiple times" is completely false though and honestly made me question if you understand the very basics of how the update loop works
@@iHeartGameDev The design pattern you're displaying is one of a state machine that internally selects when to update to new states. This means you're fully controlling when. And as others pointed out, the Unity Update loop is synchronous, and will not be multi-threaded. In fact, Unity specifically avoids anything multi-threading on their main behaviour calls and anything on the main thread specifically to not make this a concern for users of the engine. There are ways to do so like Jobs, but you don't work with MonoBehaviours in those contexts. Also, you're not allowing the states to say "Switch state now", you are instead waiting for the state manager to ask the current state if it's time to switch on it's own time. This also safeguards against asynchronous factors. The asynchronous nature would only be a problem if you allowed external calls to directly switch state immediately, i.e. a "public void SwitchStateNow(EState nextState)" method that would immediately call those transitions, which would be bad, and you're not doing it, so good job. But since you're guarded against that, it furthers the point of not needing a transition flag. External calls, if included in the design, should set a "message" (Message passing) i.e. a "private Estate queuedState", and the state manager should still do the next-state check on it's own time, and do the transition in it's own update.
I have a really hard time understanding this right now. How is this reusable? Lets say I have an Agent, that can have multiple states, like Idle, Running, Turning, etc. I would need to write specific states for that agent. So this results in having tons of extra classes at least one for each state. Every State class needs to hold an instance to my Agent class (and potentially other instances with data), so it can for example move my Agent . So the state classes become tightly coupled to my Agent instance or am I missing something? Still cool Video, it popped right up, when I'm coding an AI for my game idea and need to research that topic.
How exactly do we modify the PlayerState.Idle's methods etc after 9:04 ? Where can I implement my pre-existing methods, I'm confused... :( I am trying to refactor my old CharacterController like you did in your tutorials with this new system but I can't seem to understand. Thanks for the video though!
Would be nice to have an optional exit time that switches a state. Also a fixed follow-up state would be nice to chain states (from shoot to reload to idle). I.e. when magazine is empty, reload occurs which takes a fixed amount of time (read from animation length?) and switches to idle after reload is done. So you can define a fixed "next state" after the reload state has finished. Also a hierarchy would be nice to keep it organized :) And maybe you introduce a "state changed" event other objects can subscribe to, so they can act accordingly (i.e. a camera system that switches states depending on the player state. Switching between shoulder and normal cam when aiming state is active).
I'm trying to think of a time you would ever truly want a fixed state to be next. During a reload animation you can die, you can swap weapons, if the weapon is designed to load one bullet at a time you could even shoot. Maybe I'm misunderstanding what you're saying.
@@TheSixoul You can interrupt a State with an Event for sure (weapon swap), but you know that after a reload comes the idle state. Or you do a roll and go to idle, before walking again. Or an Attack that has to have a cooldown state. Or let's say you have a cutscene and want to bind things in order. Don't know how this is handled in professional games, but I did it like that (Press reload, do animation and wait for end, go to idle. If weapon swap, switch to another state machine and set last weapon state to reload to finish after swapping back).
public override EnvironmentInteractionStateMachine.EEnvironmentInteractionState GetNextState() { bool isOverStateLifeDuration = _elapsedTime >= _approachDuration; if (CheckShouldReset() || isOverStateLifeDuration) { return EnvironmentInteractionStateMachine.EEnvironmentInteractionState.Reset; } bool isClosestPointOnColliderReal = Context.ClosestPointOnColliderFromShoulder != Vector3.positiveInfinity; bool isWithinsReach = Vector3.Distance(Context.ClosestPointOnColliderFromShoulder, Context.CurrentShoulderTransform.position) < _riseDistanceThreshold; if (isClosestPointOnColliderReal && isWithinsReach) { return EnvironmentInteractionStateMachine.EEnvironmentInteractionState.Rise; } return StateKey; } Here's an example from one of the concrete states that will be implemented in one of the next installments in this procedural animation series. As explained in this video, CurrentState.GetNextState is run in the Update which all Concrete states must define. In the definition, if the conditions are met, it returns the next state that the state manager should transition to, otherwise it returns its own StateKey. And the StateManager checks "if the stateKey is not the same as the currentState's state key", then it should switch to the next state!
Soooo, how does this look with an actual example? I just come from your other state machine video with the apple. I understand you make an enum for the different types, but where can you put logic code for the state specific?
Great video! I'm new to state machine patterns. Could you give some examples where actual logic code is implemented in some specific use case? Would logic code be implemented in other new classes, which derrive from Statemamager, or else?
Yes, absolutely! I have a video that serves as an introduction to it: th-cam.com/video/Vt8aZDPzRjI/w-d-xo.html I think a lot of people have learned from this video!
Only thing I would really change is adding a getter for CurrentState. CurrentState is too useful of a datapoint to not have accessible. Let's say enemies, you make a sensor script to do vision/hearing, and the SensorScript can have a higher or lower range based on what the current state is.
Ideally you want to do away with enums and just make NextState return a BaseState. BaseState is also against C# naming guidelines. They’re just guidelines of course, but generally calling something “Base” is less useful than being more verbose about derived classes. Example: Truck : BaseTruck vs PickupTruck : Truck
Great video ! inherited from MonoBehaviour is not a good idea in my opinion. It would work in more cases / be more flexible if it were just an object usable by composition. But the genericity with the enum is really cool, I didn't have it in my version.
Thanks for the great content, for the next videos please zoom in the code editor a little bit, too much space on the right side is wasted and it's hard to read the codes with smaller screen.
8:25 - You imply that Unity will execute Update methods parallel which is not the case as far as I know. Even if Unity did that, creating a simple boolean guard is not sufficient for preventing race conditions among threads.
You are correct - a few people have pointed out that Unity doesn’t need to worry about this anyway because Update is synchronous. My mistake on that part
Thank you for sharing a very well edited video of your state machine implementation! I was wondering what your reason is to include the OnTriggerEnter/Exit/Stay methods in the base class and making those abstract? I see the point of having non monobehaviour base states and making the OnTrigger functionality available to the states could be beneficial, but wouldn't making those virtual instead reduce some bloating code for child classes that don't require them? Anyway great stuff!
Hey there! After a bit of script editing, the content of this video was actually abstracted out from my current series on procedural animation and how I was able to add environment interactions to my character. The only reason we removed the other collision detection and kept the trigger methods was because they aren’t necessary to that implementation. I should have made that more clear in the video, but it’s mentioned in the description now and I’ll end up updating the title most likely. Hope that makes sense and apologies for any confusion. Cheers! 🍻 -Nicky
I'm sort of new to state machines. I actually watched your first video on state machines just a few days before finding this one. Great work. However, I'm a tad confused about the Update method in the StateManager class. The first line in the method sets nextStateKey = to CurrentState.GetNextState(), but the if statement right after depends on nextStateKey being equal to whatever CurrentState.StateKey is. Unless I'm misunderstanding the purpose of the GetNextState method, I don't see how nextStateKey could ever be equal to CurrentState.StateKey when it's constantly being set to something else one line prior. Need some help understanding this if anyone knows. Still an amazing tutorial and I've learned a lot. Thanks again.
Hi, Im also new and I might also be too late to answer this. But based on my understanding, the GetNextState method is like performing some of your logic to return EState. Like you doing a check logic if it should go to another state then it will return the other states EState else it would stay the same state.
The modification of this that I made was a bit minor, but instead of using !IsTransitioning as an extra condition in the if statements, I just moved the logic to a different function (StateLoop) with a guarding if statement for IsTransitioning that returns from the function back into update, just so I don't have to repeat the check in both if statements (less of a performance thing and more a readability thing )
hi @iHeartGameDev, i discovered your channel a few days ago and i find that your approach to code in terms of quality and explanation is one of the best i've seen on youtube. i'm planning to make my first real game and i'd like to use the simplest and most modular architecture. Do you think that using a State Machine as the GameManager (initialise, restart, fail, succeed) and the Observer Pattern with scriptable objects for all the other game logic, such as the Input Reader for example, would correspond to this?
Thanks for your video! However,I have some problem when using the state machine:I would like to use IEnumerator to make a timer,but in the state class it does not have the StartCoroutine method. should I do the timer in the FixedUpdate method or change the design of state machine?
I have a question. Why change state in update? If A is the nextstate of B, B is the nextstate of A, those states will switch to each other every frames? Please light me up
I was just following your tutorial for a Hierarchical State Machine. I'm building a 2d hack and slash game, and I am mixing my movement and combat mechanics in this state machine. As a result I have 4 super states and A LOT of sub states, with their own nested states. I wanted to ask, do I have to create a script for every substates, that includes their own logic (stun, double jump, special attack, dodge etc)?
Thanks for watching my previous video! I personally would create a new script for each and place them in nested folders in your assets. In my opinion it beats the alternative of having a jumbled mess of code in a single script.
Hi, Im looking at this tutorial for two days straight, and still cant figure out this: I made PlayerStateMachine (PlayerSM) with enum EPlayerStates that is passed as generic. If I made PlayerIdleState, that inherit from BaseState. How can I in GetNextState return EPlayerStates.Walk, if i dont have access to EPlayerStates in PlayerIdleClass? I tried passing whole enum from PlayerSM when making an instance : States.Add(EPlayerStates.Idle, new PlayerIdleState(EPlayerStates)); but it cant be done. Can u help me find out what to do here? Also i dont wanna pass 4 arguments for four different states and store them so i can return them.
@@iHeartGameDev That would be legendary!! I only made the switch because of the Unity drama, but I must say I'm enjoying using Godot immensely! My workflow has been a lot better. You're one of my all time favorite game dev tutorial channels, so I would appreciate this incredibly! I love your videos!
your explanation is fantastic everyone can understand it well. I know you teach only the animation system but is there any chance to teach other stuff like Network VFX etc ... ?
Maybe someone can clear this up for me, but I don't understand how the Start() function works in this case. Would it not only load the Start() function for the currently active state, which I guess would be like the default state? Since Start() only runs one time, on startup, and it is only being called on the active state instead of all of them.
@@DapperNurd start would only run one time in the state machine, but every time the state machine switches to a new state, it would call “EnterState” which is the equivalent in this case!
Thanks for the video, it was very helpful! I followed along with the code, and when I went back into Unity, I got these errors: Assets\Scripts\BaseState.cs(5,56): error CS0246: The type or namespace name 'Enum' could not be found (are you missing a using directive or an assembly reference?) Assets\Scripts\StateManager.cs(5,75): error CS0246: The type or namespace name 'Enum' could not be found (are you missing a using directive or an assembly reference?) Assets\Scripts\StateManager.cs(7,53): error CS0314: The type 'EState' cannot be used as type parameter 'EState' in the generic type or method 'BaseState'. There is no boxing conversion or type parameter conversion from 'EState' to 'Enum'. Any tips on how to solve this problem would be greatly appreciated.
you have showed me how to give the state machine a enum of keys but how do I actually give it states from the base state class, that bit is confusing me a bit.
Hey there - thanks for watching! The end gives an example of how you’d set the Enum as the state manager’s generic. If you were to continue the implementation of a concrete state implementation, let’s say “PlayerStateMachine” for example, you would initialize the states in the Awake or Start method of the concrete state machine. That would look something like this pseodocode: Void Start() { States.Add(PlayerStates.Idle, new IdleState(PlayerStates.Idle) States.Add(PlayerStates.Walk, new IdleState(PlayerStates.Walk) States.Add(PlayerStates.Run, new IdleState(PlayerStates.Run) } Hope that helps 👍
Ahh that makes more sense I see, I was a little confused on where I go about adding the states I see now I never used a dictionary in my programming so I wasnt sure how things worked or how to use them, thanks I understand now!@@iHeartGameDev
@@Dragon20C Out of curiosity, have you had any luck implementing this? I'm getting errors as my child class is not registering as the same type as the abstract parent.
I think this looks cool, but feels like the update method is a bit heavy, checking for state every frame. Could you make a video about the same topic, but using events for state management? Update could still be used to run state.update logic I think
Hi I've seen your first tutorial on state machine, and you were passing the StateManager as argument into EnterState(), UpdateState(), and ExitState() so that there's a way to access the player's data. You didn't mention how to pass data from state manager to states in this video - will you suggest the same method here?
As dumb as this question might sound, could someone apply this same logic withing the godot C# pipeline or do they need to do a whole lot more adjustments?
Im having difficulties in trying to use your Better Statemachine in order to create concrete states. I am new to statemachines and do not have any experience in how its done using other methods. Can anyone give a sample of how a concrete state should look when using his method?
Is there a video you made explaining how to make animation specifically for you, which means that animation is not available on the internet , for example , and you want to do this
Sorry, but when you have to create a new state how do you do to create that? I mean, you create the Enum of states and where you code what happens there?
@@iHeartGameDev absolutely not! It was one of the best tutorial videos that i see haha, just missing the part of how to use it with the new baseStates, but I'll be waiting for the new videos to learn a bit more about it!
Wait.. Abstract classes? Inherited classes? Isn't that more or less a scriptable objects? I think this will be great to be implemented on a scriptable objects
No, abstract classes are kind of like a 'blueprint'. You cannot build (instance) this class, but you can use it to build more specialised classes using inheritance, that have access to this abstract class's data and behaviours. You could definitely build out a series of States as ScriptableObjects to drag-and-drop into your State Machine brain in-editor, giving you a powerful way of constructing a chain of behavioural options without needing to re-code anything.
I can seem to connect this state machine to any of the state scripts This is my first time using a state machine and i have no idea what i am doing wrong. Any kind of help or advince would be greatly apreciated
Thanks for the project. Do you see any difference between using an abstract or a custom class (non-Monobehaviour) with override methods for each state?
I want to know without deriving from BaseState how you access it using "CurrentState in StateManager", how does this work & any resources where I can get more info
It took me a frustratingly long time to grasp state machines, but your first video on those helped me immensly. Having worked with them now for a while by now, this comes at the perfect time to think and tool with it a bit more :D!
Great to hear! I hope this video helps make your own state machines even better!
@@iHeartGameDev how to use this as a PlayerStateMachin please Reply
Some points I'd make on State Machine design, since I'm quite passionate about those:
- Avoid the term "Manager" unless the system is intended to be used once in a game scene. FSMs are very frequently used in character behaviour systems to control decisions, actions, animations, sounds and so on. Those are per-entity usages. Why not just call a spade a spade. It's the state machine that handles the states, regadless of whether it's one instance or a 100 instances in a scene. No better name than just "StateMachine" imo.
- Use Message Passing. Anytime the current state or an external system wants to trigger a next state, store it in the SM in a private field instead of having the SM specifically asking the current state "hey do you have a next state for me?". Use a "private EState queuedState;" field instead.
- There's high value in talking about the differences between a SM that internally decides when to switch states, or one that expects external systems to switch. Is there deliberate intention behind the transition method being public? This allows state transitions as a direct call from external systems, instead of handling that in the SMs own Update (see the previous point).
- The dictionary approach severly restricts how State instances must be made. For one, they must be registered for every FSM when the FSM is initialized. Secondly, that also means they must be pre-defined which prevents dynamic adjustments to the state members. Thirdly, it expects a one-to-one mapping. This means a Walk vs Run state needs two separate enum values despite all the code behaviour being the exact same, only with the speed being the difference. Now imagine having a "slowedWalk", "boostedRun", "Sprint" and other variations. All of those could instead just be done during state construction, i.e.: "stateMachine.QueueNextState(new MoveState(moveSpeed))" where the moveSpeed could stay very dynamic throughout the game. There are other ways of passing movement speed but I think it serves as an example of flexible design.
- Show an implementation of the initialization of these classes, in practical examples. How is the dictionary populated, how is the first state going to be set. Should the SM assume that there is such a thing as a "default" state. Should the SM allow having no state at all in some cases?
- Flexibility in decision making. If a state needs to tell the SM what the next state is, it means that this state will act the same in most cases. Of course there can be some logic as to what state should be picked, but imagine using state for the character behaviour in an action game. If a state is to move to a location, how does the movement know what comes next? Should the character swing a sword or try open a door? A move state wouldn't know the answer without a lot of complexity that doesn't concern how movement is done (which contradicts SOLID principles). So if the movement completes, how should the next state be chosen. This ties into the use of a "default state" but also the thought about "external state decisions". This is also the biggest difference between a mere FSM and a fully fledged BehaviourTree. Although I would recommend a combination of the two.
"Anytime the current state or an external system wants to trigger a next state, store it in the SM in a private field instead of having the SM specifically asking the current state..."
Is this because it's better for states not to have references to other states? Or that a state should be dealing with it's own logic and not worrying about what needs to come next?
Wonderful wonderful write up! Thank you for taking the time to share your knowledge!
@@notadev9000 It's for the other systems to "leave a message" for the SM so that the SM holds the needed info about the next state internally until it's the correct time of the update cycle to perform the switch. You can design a SM such that it depends on current state to provide necessary state on demand, but that comes with less flexibility and potential pitfalls. For starters, the code to provide the next state on demand might be decided during the states update loop, but the state would then need to remember this until prompted by the SM to provide it, which could be the next update. Secondly, this code would likely be produced by developers using the SM you made, and you want to make the system as robust as possible when it comes to user-extended code. I.e. it's preferable to internalize expected behavior into the base classes when possible. It's easier for the user to decide the next state to run while in the hot spot of the update, rather than "recalling" that decision when the SM says it's time. Thirdly, if the SM should be open to accept external systems requests to queue a next state, then that has to be done in a different way than prompting the current state, in which case, the alternative is a solution that works for both internal and external state changes.
@@iHeartGameDev +1 For StateMachine instead of StateManager.
@kennethkrist can you maybe share link for gist with your example of state machine? What you wrote seems correct but I am having trouble wrapping my head around it 😅
It is very uncommon for GameDev videos to get as deep and accurate in the OOP concepts and patterns. Most Game Dev videos focus on "make it work", you focused on "make it ELEGANT". Plus, the implementation is perfectly balanced between simplicity and reusability. Great work !
Thank you so much for the kind words!
Even tho I knew these things already I still watched the whole thing cause it's so well edited and well explained, appreciate your work a lot man keep it up!
I appreciate that! Glad that you enjoyed it!
I loved your older tutorial about state machines. Right now, your type of implementation is what I commonly use, with some tweaks!
I just opened TH-cam because I want to see other state machine's implementations and KABOOM! You are here. Amazing, as always a very nice video.
Keep on!
Thank you so much! I’m glad you liked my old videos and hope you like my new one!
After about a week of frustration trying to wrap my head around it, I've finally managed to use this and your last couple of state machine videos to create a reuseable heirarchical state machine 🎉 Now to implement it as a character controller using event based state changes 😅 Thanks for the fantastic tutorials!
That’s fantastic!! I haven’t even done a hierarchical state machine with this yet. Congrats!
8:40 Update is called on the mainthread, there is no parallelization happening. As long as no ExitState or EnterState method calls "TransitionToState" there is no need for "IsTransitioningState". Update is also only called Once per frame.
Also, I find the design questioning that your state decides the following state. The state should not depend on other states at all, keeping it modular and interchangeable. the transitions should be defined on the state machine (or state manager) - imho. There might be applications for changing this, but I'm referring to a general purpose state machine
Hello! You are correct - others have pointed that out and it’s my mistake. I’ll likely correct it in a future video.
As for the second point, that’s understood and reasonable, but I would say there are benefits to both the state manager deciding the conditions for transitioning or this implementation where the states do. In the future, I’ll probably make a video where the state manager handles it, as well.
but if u also have a fixedupdate call this is good right?
@@headecas All unity methods are called on the main thread (including FixedUpdate). Parallelization only happens in unity when you explicitly implement it for a method (Like when using Unity's Jobs system).
@@heptagram064 ty m8
State deciding on the following state is useful when you have a lot of states and need to keep the state machine free from bloat. Then again, I suppose you're suggesting the state machine calls the transition method on the current state and passes the next state, or something like that?
One of my main languages in c# (enterprise stuff) and this was nice and clean. well done. doing my own game atm. your doing well on these resources! Better than the usual throw code together approach from a lot on youtube.
✨Very excited to share a new tutorial with you all! What is your favorite design pattern? It's pretty clear what mine is... 😂
State Pattern is really powerful and I used it in computer science all the time (since computers are state machines, do'h).
But I think the subscriber pattern is the most powerful, since you get rid of polling which can be really taxing on your performance.
I’m pretty fond of the observer pattern. Callbacks feel like magic to me.
Strategy Pattern. Probably the most simple one there is.
It's always nice to see more about fsms. Something I would like to see in event-based transitions!
Alex!! Thank you 🙏 and agreed! That’ll be the next upgrade I make for sure
Since this was insanely helpful when I was using Unity, I'm coming back to use this as reference for implementing this into Godot 4. Easily the best explanation of State Machines
Thank you so much!
Very nice way to explain it. I love the graphics to give the overhead view and understanding of the concepts
Thank you so much for sharing this with us. As a hobbyist gamedev I admit this is still beyond my complete comprehension but I am much closer to fully understanding it. Your video was very well put together and I'm sure I'll be referencing it in the future.
Thank you for such kindness!!
It's also useful to have a method to reset the state when the transition is happening (although that can just be inserted into the Exit method, I just find it cleaner to have a separate method for it).
That is for when states are reused and not recreated (for example to avoid garbage allocation - it's a microoptimization for performance since on devices like mobile, a run of the garbage collector can actually cause some microstuttering - also tied into that: Dictionaries with enum keys will generate garbage as well. A workaround would be to a dictionary that maps from int to the state. This is a bit less type safe though).
Another interesting implementation I've seen is to not deal with Enums, but with the "Type" type directly as dictionary key type.
Then there are possibly some other design decisions people can make for themselves: Should the state machine manager check for a changed state itself, like here, or should each state trigger the Transition method directly. Is it allowed to transition from a type of state to the same type, or not? (most often, it is probably not necessary)
What might also be useful is some sort of shared data container to store state in, so that states can cross access this. Such a container could be created by the state machine, or passed into the state machine, and then passed on to each state (for example through the state constructor).
Hey thanks for the detailed response. Can you provide an example of the "Type" type -- I have not seen that before but one other community member mentioned it?
@@iHeartGameDev from the top of my head - you could have a dictionary of type Dictionary or Dictionary and then initialize the dictionary with the types of available states for keys and their respective instances as value, either manually or with reflection (e.g. with Activator.CreateInstance(..)). Then, if the SetState in the state machine class is called, it can take a parameter of "System.Type", then will check if the respective key is available in the dictionary, and if so, switch to that state. (stateManager.SetState(typeof(CharacterStates.SprintState));
Sometimes my BasteState class also just uses virtual methods with an empty method body instead of abstract methods, so that the actual state implementations don't have to implement all methods, if they don't need specific logic for it (for example some states might not care about trigger interactions)
Ur Explanation Is Very Clear Please Dont Stop Doing it ❤
Thank you Mohamed! I’ll keep going!
Thank you for making this!
I'll share it with my students! 📚
Hope you enjoyed it, Alan! Thanks for sharing!
I happen to be learning about state machine lately and this tutorial shows up right on time xD
It's the best design pattern (in my opinion)! Hope this helps!
One tip.
At 8:44 you can use a guard clause for IsTransitioningState. It will increase your code readability.
Thank you, this was really helpful! Just in time for my next game jam. I had been looking for a way to refactor my overly complicated state machine mess, and this was it! It integrates perfectly with my current system
Awesome! I hope this helps you!
Great video! I've seen some comments suggesting that statemachine should control when states change, i would say it highly depends on use cases. If you have need for more dynamic statemachine like a hybrid of behaviour tree than yes, this is trouble, but i can see a lot of use cases when this implementation will save statemachine to be bloated and delegate functionality to states themselves. Cool stuff!
Thanks so much for watching and for the kind words and insight! Everything is contextual in programming imo… there are certainly best practices but even those have multiple avenues and competitors as to how something can be done. Well said!
*furious note taking*
Lol hope this helps with your game!
@@iHeartGameDev always does :)
Excellent intermediate coding video 🎉
Thanks so much!
It might be useful to include variants of this implementation such as utilising a stack in your FSM brain to return to a base state after completion. This would help for menus, states like attack follow-up/combinations and may not be immediately obvious for a fresh game developer.
Interesting! I think keeping videos concise is important, so I'd be curious if there's an idea for a follow up video about it
@@iHeartGameDev Personally, as someone who is learning, I really like the longer videos. There is no shortage of short tutorials, and usually those don't even scratch the surface of more complex topics such as this. But I do understand that you also make them with engagement in mind.
Either way, I appreciate you taking the time out to make this series!
Oh, that's cool! I always wondered when to use a stack and this seems like the perfect usage. Would be perfect for the turn-based game I'm working on.
So, you'd do something like: In your attack menu, add the attack menu state to the stack. Then once you pick the attack, you slap that bad boy onto the stack too. Then whatever your attack does gets slapped on there, such as a targeting menu, cinematic, and what have you. Is that more or less correct?
@@noctisocculta4820 A stack is first-in, last-out so it's great for when you need to 'unwind' back to a state once something is complete.
Taking your menu example, the UI would open your initial list of options. Let's say we hit attack. The attack menu opens up. We now see a list of special attacks we can do. We select one. Now it pops up a list of targets on the UI. We select one and off it goes!
Each of those UI panels are a state. But they are only there until we select an option. After we've done all the selecting or we change our mind, we want to unwind and drop all those states to return back to the previous state or clear the states so the base can handle finishing up.
We cannot continue to pop things on the stack indefinitely. It's power in this use case comes from being to stash the context of previous states despite being in the 'next' state, allowing us to unwind the stack quickly and easily.
@@_KB88 Thanks for the reply! Awesome, so my example would work the way I thought it might.
Every time I've made a system it always gets super complicated, and I give up under its weight - thanks to you, I think I can make a lightweight, readable system that can be extended without cognitive overwhelm/ refactoring.
Cheers, mate.
Hey man I really really like your videos. I have struggled quite a lot with state machines, yet i`m still struggling with some stuff but you are making it really easy for everyone to understand. I generally got a good idea how do state machine works, yet I still lack some understanding how to implement movement controls (as for fps character).
So, I would like to ask you, if possible, maybe in a future video to show us an example of FSM of a FPS controller (based on a rigid body movement) and the new unity input system (which is based on input events). I assume since it's really hard for me to grasp all the aspects of it, that there are lot of people having the same troubles. Thank you for all the good tutorials so far!!!
Awesome tutorial as always, learned about state machines in your previous videos on the topic! :)
However I would appreciate a few minutes of how to use it, create concrete states, add them to dictionary - actual usage. I find it a bit confusing to get started with this!
Anyhow, great video, awesome editing etc! Keep up the good work ,you rock!!
Glad you liked it! The rest of the procedural animation series will provide the insight needed for a concrete implementation!
Another great video. Please show how to create a 3rd person character controller using this better state machine and the new input system. Thank you!
Thank you Steven! My next video is a practical example of how to set up a state machine with this base implementation. It will be for the procedural animation series though instead of 3rd person character controller. Hopefully the walkthrough is enough to get an understanding for you
Hi, i just wanna let you know that i learnt various state machine and i think yours is best for me as a beginner. I implemented a similar state machine in my ebook and specifically mention your TH-cam channel. The book title is How I get tricked by Unity and it is on amazon now. Please there is no need to buy or advertise. I get only penny out of this book and i just try to share how beginners like me can code in Unity. I put your link on page 519. If you wish to have a look, please feel free to drop me a note and i can print screen. Anyway, thank you very much for your sharing! Keep up your good work.
Flamming
Thank you for the callout! That's incredibly kind!
Incredibly useful and well explained, as always
Hello, can you show me the constructor method of an example state class?
This was very informative and well explained! 🙏🏻
Thank you!!
Thank you for a great explanation!
Thank you for watching! Hope it helps!
I am confused as to where the logic for these states go. I made a few classes inheriting from BaseState e.g "public class IdleState : BaseState"... I haven't been able to figure out how to use the enum to get this state though. I wonder if maybe I have completely misunderstood the idea here.
In the same boat here, not sure how to actually create a key for the state and then give it
Great video. Very informative and well presented. I think there are some improvements that you could make.
In the Update, you should short circuit if "isTransitioningState" is true before you call "GetNextState()" so that it doesn't get called every frame. IMO, it's more readable as well. You can see at a glance which conditions will cause subsequent logic to skip.
When building abstract classes I think it's important to be as performant as possible. Instead of an update that constantly checks whether the state changes, it would be better to implement an event driven solution. That's probably outside of the scope for this video, though.
Overall, great tutorial!
I love these points - thank you for watching and for sharing your knowledge! I’ll give them a test for my next implementation
Very nice pattern! Thank you so much for sharing. My two cents about it: making the methods of BaseState 'virtual' instead of abstract would allow not to implement them if not needed, leading to less clutter in the implemented states.
LOL I was just talking about State Machines and your videos with my colleagues 20 minutes ago.
Absolutely love to hear that. Kinda crazy tbh
Finallyyy 😭😭💖💖💖 thank you so much, I can't wait to get my hands on this code!!
Thank you for the kindness!
And there he is with another great video.
Thank you 🙏
How do manage a character, that can have multiple states at once?
For example: You attack, while jumping or you block, while walking.
A hierarchical state machine and multiple state machines :)
Any plans on potentially expand on this and explain how to incorporate support for substates? And as many others have pointed out, event-based statechanges and such would be very appreciated! That said, fantastic video. I'm trying to learn more about FSM's so this was great. :)
You're the second to ask about it, and I do love hierarchical state machines so I'll definitely add it to my list of content to cover in the near future. And I've also gathered that the event-based state change is recommended by a bunch of people, which I'm happy to take a look into!
@@iHeartGameDev I hope it'll come to fruition, that'd be exciting!
worked! thank you a lot
Awesome! Love that!
Your uploads are always extremely helpful!
I wonder if we could get a video on Behavior Trees some day! 😃
Moving to Godot but as great part of your explanations are engine agnostic or can be tried out without much hassle I'll keep following you, thanks for this superb video!
Thanks so much! I'm also thinking about making tutorials in Godot! Maybe I'll do a state machine video :D
Hey, I remember recommending using the dictionary to cache your states way back then. Now here you are, teaching me a new and clean way to reuse state machines! I love how that works.
I am curious, why are you handling state swapping the way you are? From what I can see, you're taking the indirect approach of having the states return their own keys when asked for the next state key in GetNextState. Wouldn't it be easier to put the responsibility on the states themselves to call the TransitionToState(State stateKey)?
As I'm typing this, I realize that by having the states return the next state with a method call, you don't have to cache the state manager! Thats clever, very clever.
I find myself bogged down not only by repeatedly making state machines, I always have extra code for keeping that reference in the states. You've taught me two things today!
:) I remember your recommendation! I’m happy to see you return! There are definitely still improvements that I can make. Looks like this won’t be the last state machine video I make!
Wait, at 8:20, how could Update() be called multiple times before going through all instructions if the code is executing on the main thread?
I believe it's necessary in multi-threaded scenarios and if there are asynchronous operations that could potentially interfere with the state transitions. Your point is valid though -- it might be redundant at the moment!
Oh ok. It's been years since I haven't coded games, so I was just making sure I hadn't forgotten some basic concepts. Btw, thanks for the great video!
@@theReimy thanks for making a great point and for watching!
I admire your perseverance. You are obviously very passionate about some coding patterns (like State Machines lol) and you try to teach them to the Unity community, which is dominated by beginner level coders trying to "make a game" and quitting after it gets serious.
Even though the reception of such more intermediate level lessons is not as good as of the standard "flashy FPS game unity tutorial" you don't let yourself get drifted towards the easy market. And for that I wanted to say thanks!
Something I would like to see discussed is when to split certain behaviors between multiple state machines vs creating an often complicated hierarchy within a single state machine.
I would always get tripped up by whether to keep a player’s traversal state (walk, run, idle) separate from a combat state (attacking, guarding etc.).
In summary: when should an SM be split into multiple SMs even if the behaviors interact with each other? (Ex: can only perform certain attack when in x state etc)
That does sound like an interesting topic!
In summary: when should an SM be split into multiple SMs even if the behaviors interact with each other? (Ex: can only perform certain attack when in x state etc)
But doing so complicates the problem, we can try the ability to switch when combining a number of keys into a set of states or a certain key to exit a certain state and have a flexible transition.
Awesome, thanks for the series.
You’re welcome! I hope you enjoy it!
Great video! However, I don't quite understand why we need to check for IsTransitioningState. Following this implementation, Update() is a synchronous method and therefore all of the code (of this and every other Update() method) is executed before the next Update() is invoked. Therefore, there cannot be multiple state transitions at the same time. Even with event-based state transitions, I don't see why we need to check this, as the events should be handled in sequence and not in parallel. Am I wrong?
Another community member pointed this out! I believe it's necessary in multi-threaded scenarios and if there are asynchronous operations that could potentially interfere with the state transitions. Your point is valid though -- it might be redundant at the moment!
we could add a “transitioning state” if we want the “one frame transition” behaviour (eg Hidden, Appearing, Appeared, Hiding). or with this implementation, we only have two states (Hidden, Appeared) but allow the transition to happen across few frames.
@@iHeartGameDev the explanation about how "different framerate can make the function be called multiple times" is completely false though and honestly made me question if you understand the very basics of how the update loop works
@@iHeartGameDev The design pattern you're displaying is one of a state machine that internally selects when to update to new states. This means you're fully controlling when. And as others pointed out, the Unity Update loop is synchronous, and will not be multi-threaded. In fact, Unity specifically avoids anything multi-threading on their main behaviour calls and anything on the main thread specifically to not make this a concern for users of the engine. There are ways to do so like Jobs, but you don't work with MonoBehaviours in those contexts.
Also, you're not allowing the states to say "Switch state now", you are instead waiting for the state manager to ask the current state if it's time to switch on it's own time. This also safeguards against asynchronous factors.
The asynchronous nature would only be a problem if you allowed external calls to directly switch state immediately, i.e. a "public void SwitchStateNow(EState nextState)" method that would immediately call those transitions, which would be bad, and you're not doing it, so good job. But since you're guarded against that, it furthers the point of not needing a transition flag. External calls, if included in the design, should set a "message" (Message passing) i.e. a "private Estate queuedState", and the state manager should still do the next-state check on it's own time, and do the transition in it's own update.
this'll enhance my term project, ngl
I have a really hard time understanding this right now. How is this reusable? Lets say I have an Agent, that can have multiple states, like Idle, Running, Turning, etc. I would need to write specific states for that agent. So this results in having tons of extra classes at least one for each state. Every State class needs to hold an instance to my Agent class (and potentially other instances with data), so it can for example move my Agent . So the state classes become tightly coupled to my Agent instance or am I missing something?
Still cool Video, it popped right up, when I'm coding an AI for my game idea and need to research that topic.
wow never seen this method before!
Thanks for watching!
How exactly do we modify the PlayerState.Idle's methods etc after 9:04 ? Where can I implement my pre-existing methods, I'm confused... :(
I am trying to refactor my old CharacterController like you did in your tutorials with this new system but I can't seem to understand. Thanks for the video though!
Would be nice to have an optional exit time that switches a state.
Also a fixed follow-up state would be nice to chain states (from shoot to reload to idle).
I.e. when magazine is empty, reload occurs which takes a fixed amount of time (read from animation length?) and switches to idle after reload is done.
So you can define a fixed "next state" after the reload state has finished.
Also a hierarchy would be nice to keep it organized :)
And maybe you introduce a "state changed" event other objects can subscribe to, so they can act accordingly (i.e. a camera system that switches states depending on the player state. Switching between shoulder and normal cam when aiming state is active).
I'm trying to think of a time you would ever truly want a fixed state to be next. During a reload animation you can die, you can swap weapons, if the weapon is designed to load one bullet at a time you could even shoot. Maybe I'm misunderstanding what you're saying.
@@TheSixoul You can interrupt a State with an Event for sure (weapon swap), but you know that after a reload comes the idle state. Or you do a roll and go to idle, before walking again. Or an Attack that has to have a cooldown state. Or let's say you have a cutscene and want to bind things in order.
Don't know how this is handled in professional games, but I did it like that (Press reload, do animation and wait for end, go to idle. If weapon swap, switch to another state machine and set last weapon state to reload to finish after swapping back).
I think you could return a BaseState directly instead of using generics and the enum. So basically the GetNextState returns the new target state.
So I am having an error The given key “Idle” was not present in the dictionary while I was trying to make a player state machine. How do I add key?
Thanks for video but I can't understand one think. How can I handle transition between states ? Can you give me an example ? Thank you!
public override EnvironmentInteractionStateMachine.EEnvironmentInteractionState GetNextState()
{
bool isOverStateLifeDuration = _elapsedTime >= _approachDuration;
if (CheckShouldReset() || isOverStateLifeDuration)
{
return EnvironmentInteractionStateMachine.EEnvironmentInteractionState.Reset;
}
bool isClosestPointOnColliderReal = Context.ClosestPointOnColliderFromShoulder != Vector3.positiveInfinity;
bool isWithinsReach = Vector3.Distance(Context.ClosestPointOnColliderFromShoulder, Context.CurrentShoulderTransform.position) < _riseDistanceThreshold;
if (isClosestPointOnColliderReal && isWithinsReach)
{
return EnvironmentInteractionStateMachine.EEnvironmentInteractionState.Rise;
}
return StateKey;
}
Here's an example from one of the concrete states that will be implemented in one of the next installments in this procedural animation series. As explained in this video, CurrentState.GetNextState is run in the Update which all Concrete states must define. In the definition, if the conditions are met, it returns the next state that the state manager should transition to, otherwise it returns its own StateKey. And the StateManager checks "if the stateKey is not the same as the currentState's state key", then it should switch to the next state!
@@iHeartGameDev Thank you so much
Hello again, I have question about State Enums. How I can make a connection State Enum to State Class ?
Great job man
Thanks so much!
Soooo, how does this look with an actual example? I just come from your other state machine video with the apple. I understand you make an enum for the different types, but where can you put logic code for the state specific?
Great video!
I'm new to state machine patterns.
Could you give some examples where actual logic code is implemented in some specific use case?
Would logic code be implemented in other new classes, which derrive from Statemamager, or else?
Yes, absolutely! I have a video that serves as an introduction to it: th-cam.com/video/Vt8aZDPzRjI/w-d-xo.html
I think a lot of people have learned from this video!
Only thing I would really change is adding a getter for CurrentState. CurrentState is too useful of a datapoint to not have accessible. Let's say enemies, you make a sensor script to do vision/hearing, and the SensorScript can have a higher or lower range based on what the current state is.
That's fair! Appreciate the input -- and thank you for watching!
Nice design!
Thank you! Cheers!
How to use it for movement character or jump or attack?
Ideally you want to do away with enums and just make NextState return a BaseState.
BaseState is also against C# naming guidelines. They’re just guidelines of course, but generally calling something “Base” is less useful than being more verbose about derived classes. Example:
Truck : BaseTruck
vs
PickupTruck : Truck
Great video ! inherited from MonoBehaviour is not a good idea in my opinion. It would work in more cases / be more flexible if it were just an object usable by composition. But the genericity with the enum is really cool, I didn't have it in my version.
I love this tutorial
Amazing video! What is the theme that you use for Rider ?
Thank you - I don’t use rider. This is all VS Code with the Happy Hipster theme
Any chance you can showcase some states like idle walk etc
Hey, yes! Stay tuned for more parts in the procedural animation series! Next episode we set up the environment interaction state and context
Thanks for the great content, for the next videos please zoom in the code editor a little bit, too much space on the right side is wasted and it's hard to read the codes with smaller screen.
Noted!
8:25 - You imply that Unity will execute Update methods parallel which is not the case as far as I know. Even if Unity did that, creating a simple boolean guard is not sufficient for preventing race conditions among threads.
You are correct - a few people have pointed out that Unity doesn’t need to worry about this anyway because Update is synchronous. My mistake on that part
Oh, sorry I didn't notice. Anyway I like your videos and we are all learning here so keep up the good work!
Thank you for sharing a very well edited video of your state machine implementation!
I was wondering what your reason is to include the OnTriggerEnter/Exit/Stay methods in the base class and making those abstract? I see the point of having non monobehaviour base states and making the OnTrigger functionality available to the states could be beneficial, but wouldn't making those virtual instead reduce some bloating code for child classes that don't require them?
Anyway great stuff!
I was wondering the same and also why tie state transitions to collider triggers at all?
Likewise. This introduces useless data into the other states that don't care about collisions/triggers (menus, for example).
Hey there! After a bit of script editing, the content of this video was actually abstracted out from my current series on procedural animation and how I was able to add environment interactions to my character. The only reason we removed the other collision detection and kept the trigger methods was because they aren’t necessary to that implementation. I should have made that more clear in the video, but it’s mentioned in the description now and I’ll end up updating the title most likely. Hope that makes sense and apologies for any confusion.
Cheers! 🍻
-Nicky
Awesome tutorial, but do you have a simple example of how this is best implemented?
I'm sort of new to state machines. I actually watched your first video on state machines just a few days before finding this one. Great work. However, I'm a tad confused about the Update method in the StateManager class. The first line in the method sets nextStateKey = to CurrentState.GetNextState(), but the if statement right after depends on nextStateKey being equal to whatever CurrentState.StateKey is. Unless I'm misunderstanding the purpose of the GetNextState method, I don't see how nextStateKey could ever be equal to CurrentState.StateKey when it's constantly being set to something else one line prior. Need some help understanding this if anyone knows. Still an amazing tutorial and I've learned a lot. Thanks again.
Hi, Im also new and I might also be too late to answer this. But based on my understanding, the GetNextState method is like performing some of your logic to return EState. Like you doing a check logic if it should go to another state then it will return the other states EState else it would stay the same state.
Is this only applicable to newer versions of Unity? Getting an error that EState can't be used as a parameter.
The modification of this that I made was a bit minor, but instead of using !IsTransitioning as an extra condition in the if statements, I just moved the logic to a different function (StateLoop) with a guarding if statement for IsTransitioning that returns from the function back into update, just so I don't have to repeat the check in both if statements (less of a performance thing and more a readability thing )
hi @iHeartGameDev, i discovered your channel a few days ago and i find that your approach to code in terms of quality and explanation is one of the best i've seen on youtube. i'm planning to make my first real game and i'd like to use the simplest and most modular architecture. Do you think that using a State Machine as the GameManager (initialise, restart, fail, succeed) and the Observer Pattern with scriptable objects for all the other game logic, such as the Input Reader for example, would correspond to this?
Thanks for your video! However,I have some problem when using the state machine:I would like to use IEnumerator to make a timer,but in the state class it does not have the StartCoroutine method. should I do the timer in the FixedUpdate method or change the design of state machine?
I have a question. Why change state in update? If A is the nextstate of B, B is the nextstate of A, those states will switch to each other every frames? Please light me up
Normally there are conditions that must be met in order for the transition to the next state to be met, so this shouldn’t be an issue 👍
@@iHeartGameDev Thanks. Your videos are cool and they help me a lot on my way to learning about design patterns
I was just following your tutorial for a Hierarchical State Machine. I'm building a 2d hack and slash game, and I am mixing my movement and combat mechanics in this state machine. As a result I have 4 super states and A LOT of sub states, with their own nested states. I wanted to ask, do I have to create a script for every substates, that includes their own logic (stun, double jump, special attack, dodge etc)?
Thanks for watching my previous video! I personally would create a new script for each and place them in nested folders in your assets. In my opinion it beats the alternative of having a jumbled mess of code in a single script.
@@iHeartGameDev thank you king!
Hi, Im looking at this tutorial for two days straight, and still cant figure out this: I made PlayerStateMachine (PlayerSM) with enum EPlayerStates that is passed as generic. If I made PlayerIdleState, that inherit from BaseState. How can I in GetNextState return EPlayerStates.Walk, if i dont have access to EPlayerStates in PlayerIdleClass? I tried passing whole enum from PlayerSM when making an instance : States.Add(EPlayerStates.Idle, new PlayerIdleState(EPlayerStates)); but it cant be done. Can u help me find out what to do here? Also i dont wanna pass 4 arguments for four different states and store them so i can return them.
YES! I got this video just when I needed it!!! Thank you!
I'm using Godot now, but I'm sure it'll apply over
Awesome 👏 maybe it makes sense for me to try out making a state machine tutorial for Godot??
@@iHeartGameDev That would be legendary!! I only made the switch because of the Unity drama, but I must say I'm enjoying using Godot immensely! My workflow has been a lot better.
You're one of my all time favorite game dev tutorial channels, so I would appreciate this incredibly! I love your videos!
your explanation is fantastic everyone can understand it well. I know you teach only the animation system but is there any chance to teach other stuff like Network VFX etc ... ?
Thank you Raymond! Appreciate the kind words! I’d love to get into other aspects of game engines 👍 just a matter of time
Maybe someone can clear this up for me, but I don't understand how the Start() function works in this case. Would it not only load the Start() function for the currently active state, which I guess would be like the default state? Since Start() only runs one time, on startup, and it is only being called on the active state instead of all of them.
@@DapperNurd start would only run one time in the state machine, but every time the state machine switches to a new state, it would call “EnterState” which is the equivalent in this case!
@@iHeartGameDev Ah I see. I somehow missed that. Thanks!
That's excelent~
Thank you for the kind words!
And now I'm following your video and remaking state machines onto PIC18 microcontroller that has no OOP support whatsoever
Thanks for the video, it was very helpful! I followed along with the code, and when I went back into Unity, I got these errors:
Assets\Scripts\BaseState.cs(5,56): error CS0246: The type or namespace name 'Enum' could not be found (are you missing a using directive or an assembly reference?)
Assets\Scripts\StateManager.cs(5,75): error CS0246: The type or namespace name 'Enum' could not be found (are you missing a using directive or an assembly reference?)
Assets\Scripts\StateManager.cs(7,53): error CS0314: The type 'EState' cannot be used as type parameter 'EState' in the generic type or method 'BaseState'. There is no boxing conversion or type parameter conversion from 'EState' to 'Enum'.
Any tips on how to solve this problem would be greatly appreciated.
What coding pattern we should use for making games that involves at lot of movements?
you have showed me how to give the state machine a enum of keys but how do I actually give it states from the base state class, that bit is confusing me a bit.
Hey there - thanks for watching! The end gives an example of how you’d set the Enum as the state manager’s generic. If you were to continue the implementation of a concrete state implementation, let’s say “PlayerStateMachine” for example, you would initialize the states in the Awake or Start method of the concrete state machine. That would look something like this pseodocode:
Void Start() {
States.Add(PlayerStates.Idle, new IdleState(PlayerStates.Idle)
States.Add(PlayerStates.Walk, new IdleState(PlayerStates.Walk)
States.Add(PlayerStates.Run, new IdleState(PlayerStates.Run)
}
Hope that helps 👍
Ahh that makes more sense I see, I was a little confused on where I go about adding the states I see now I never used a dictionary in my programming so I wasnt sure how things worked or how to use them, thanks I understand now!@@iHeartGameDev
@@iHeartGameDevThis should be added in description or as a pinned comment.
@@Dragon20C Out of curiosity, have you had any luck implementing this? I'm getting errors as my child class is not registering as the same type as the abstract parent.
I think this looks cool, but feels like the update method is a bit heavy, checking for state every frame. Could you make a video about the same topic, but using events for state management?
Update could still be used to run state.update logic I think
Oooo I really like this idea. I’ll check into it for sure! Thank you
can you show how you would implment this.
Hi! The rest of the series will show the full implementation of the environment interaction state machine!
Hi I've seen your first tutorial on state machine, and you were passing the StateManager as argument into EnterState(), UpdateState(), and ExitState() so that there's a way to access the player's data. You didn't mention how to pass data from state manager to states in this video - will you suggest the same method here?
As dumb as this question might sound, could someone apply this same logic withing the godot C# pipeline or do they need to do a whole lot more adjustments?
I'd love to build this in Godot as well!
Im having difficulties in trying to use your Better Statemachine in order to create concrete states. I am new to statemachines and do not have any experience in how its done using other methods. Can anyone give a sample of how a concrete state should look when using his method?
Is there a video you made explaining how to make animation specifically for you, which means that animation is not available on the internet , for example , and you want to do this
Sorry, but when you have to create a new state how do you do to create that? I mean, you create the Enum of states and where you code what happens there?
Nothing to apologize for - I’ll have a few follow up videos coming soon with examples! Sorry that it wasn’t clear without that!
@@iHeartGameDev absolutely not! It was one of the best tutorial videos that i see haha, just missing the part of how to use it with the new baseStates, but I'll be waiting for the new videos to learn a bit more about it!
I have followed this but I am just lost on how to implement this using what has been set up. I just cant seem to wrap my head around it. Any help?
Wait.. Abstract classes? Inherited classes? Isn't that more or less a scriptable objects?
I think this will be great to be implemented on a scriptable objects
No, abstract classes are kind of like a 'blueprint'. You cannot build (instance) this class, but you can use it to build more specialised classes using inheritance, that have access to this abstract class's data and behaviours.
You could definitely build out a series of States as ScriptableObjects to drag-and-drop into your State Machine brain in-editor, giving you a powerful way of constructing a chain of behavioural options without needing to re-code anything.
_KB88 is correct! There are multiple ways to implement a state machine, including scriptable objects. My preference is abstract classes
Oh heck yes!
I can seem to connect this state machine to any of the state scripts
This is my first time using a state machine and i have no idea what i am doing wrong.
Any kind of help or advince would be greatly apreciated
Thanks for the project. Do you see any difference between using an abstract or a custom class (non-Monobehaviour) with override methods for each state?
If we don’t implement an abstract class, can we guarantee that every class implements the same methods to override?
I want to know without deriving from BaseState how you access it using "CurrentState in StateManager", how does this work & any resources where I can get more info
Hey! BaseState is just a public class type so the type is available anywhere in this project’s scripts