The name seems really fancy, but it wasn't really my idea.
You can look trough Unreal Tournament code base on GitHub if you are subscriber, to see for their state machine used with Weapons.
It's very nice concept, though in UT version it is directly tied to Weapon class. In their case there is nothing wrong with that. As it is pretty much the only place where they might this kind of state machine.
In my case I needed something more generalized and not tied to specific class in inheritance hierarchy. My first try was with implementing it trough interfaces, It didn't really worked out, because state machine needs some information about object that owns it.
Next I tried to move it into ActorComponent, which now makes more sense. It only needs to be implemented once, and can be attached to any actor you wish. It doesn't pose any special requirement on actor beyond one. To really make use of state machine you should implement Interface IIARActionState, which contain few functions and entry function called InputPressed(). You might get it working without this interface, but you still need to implement some sort of input handling for your actor, or trigger the State change chain in other way.
I decided to go with interface route, because I will need to add State machine to Abilities and Weapons. Especially ones like Bows, Guns, etc. With interface they don't have to share the same inheritance hierarchy, they only must share single interface. It will make easier time creating GUI later and triggering actions, regardless of which class implements them.
ActionStateComponent provide Delegate Events exposed to blueprint, for easier implementation an ability or weapon directly inside blueprints. Events are triggered as state changes it works behind the scenes and if you use blueprint you don't need to worry about it.
States are never replicated from server to client. Client doesn't even know such thing as state exists. If you want to use this system with multiplayer game you will need to implement you own client prediction for things like Casting time or Cooldown Time.
I didn't bother to try make states replicable, because the cases where you would really want state on client side are very niche, and implementing client prediction for displaying numbers is fairly trivial.
Currently states work based on Actor Tick(), but this is not set in stone, and I might change it use World Timer Manager, if it proves to be more efficient and/or easier to use.
Supported State:
Things that will be added:
Also State Chain is as fallows (please note this is not complete and might change):
Active (when action is equipped) > Action Cast (Type is specified by class in Blueprint) > Cooldown > Active.
It currently lack of inactive state, where action is in our possession but we can't use it until it is equipped.
I think this pretty much cover any action you might imagine. If there is something special, you are welcome to add it ;).
You can find code here:
GitHub Repository
You can look trough Unreal Tournament code base on GitHub if you are subscriber, to see for their state machine used with Weapons.
It's very nice concept, though in UT version it is directly tied to Weapon class. In their case there is nothing wrong with that. As it is pretty much the only place where they might this kind of state machine.
In my case I needed something more generalized and not tied to specific class in inheritance hierarchy. My first try was with implementing it trough interfaces, It didn't really worked out, because state machine needs some information about object that owns it.
Next I tried to move it into ActorComponent, which now makes more sense. It only needs to be implemented once, and can be attached to any actor you wish. It doesn't pose any special requirement on actor beyond one. To really make use of state machine you should implement Interface IIARActionState, which contain few functions and entry function called InputPressed(). You might get it working without this interface, but you still need to implement some sort of input handling for your actor, or trigger the State change chain in other way.
I decided to go with interface route, because I will need to add State machine to Abilities and Weapons. Especially ones like Bows, Guns, etc. With interface they don't have to share the same inheritance hierarchy, they only must share single interface. It will make easier time creating GUI later and triggering actions, regardless of which class implements them.
ActionStateComponent provide Delegate Events exposed to blueprint, for easier implementation an ability or weapon directly inside blueprints. Events are triggered as state changes it works behind the scenes and if you use blueprint you don't need to worry about it.
States are never replicated from server to client. Client doesn't even know such thing as state exists. If you want to use this system with multiplayer game you will need to implement you own client prediction for things like Casting time or Cooldown Time.
I didn't bother to try make states replicable, because the cases where you would really want state on client side are very niche, and implementing client prediction for displaying numbers is fairly trivial.
Currently states work based on Actor Tick(), but this is not set in stone, and I might change it use World Timer Manager, if it proves to be more efficient and/or easier to use.
Supported State:
- Cooldown. Useful for ammo reload in weapon or for spell recast. Covers all cases when you need to deny access to some action for certain amount of time.
- Active. Action is active and can be used.
- Casting. Action is being used and cast. You press the input button and action is is start charging automatically, After set amount of time it is fired. Works like any spell casting MMO you might have seen
Things that will be added:
- Channeled. Action is channeled as for set period of time, and on each interval event is fired indicated that, interval time has been reach, and you can fire rest of your action.
- Instant. Not really a state, because Casting with 0 time is effectively instant. But it might go as seprate class, just to lessen confusion.
- Cast Charged. The action is charged while you press input button down. When you release button charging stop and action is not fired. When MaxChargeTime is reached action is fired.
- Channeled Charged. Action is channeled as long as you hold input button down or until you reach MaxChargeTime.
Also State Chain is as fallows (please note this is not complete and might change):
Active (when action is equipped) > Action Cast (Type is specified by class in Blueprint) > Cooldown > Active.
It currently lack of inactive state, where action is in our possession but we can't use it until it is equipped.
I think this pretty much cover any action you might imagine. If there is something special, you are welcome to add it ;).
You can find code here:
GitHub Repository