(Sorry I didn’t get this out sooner, I got distracted)
I mentioned in my last post about how I am making a better AI, but didn’t really explain how I did it. My big problem with a lot of devs is that they never really explain how they do anything, really. They show off this product, and love to talk about the process in general, but when you ask about what exactly they did, no response.
The AI in Starfire at the current released version is a pseudo-FSM based system, with three states: Idle, Attack, and Dodge. If you don’t know what FSM is, it is Finite State Machine, which in a phrase is a flow chart. That is a bit of a simplification, but it gets the idea across.
Each state is one bubble in the flow chart, and various things can be used as the arrows. In the case of the current AI, the bubbles are pseudo-states, because there are no defined states. Instead, each pseudo-state is always executed, each time the agent thinks. In other words, the AI always attacks, does the idle action, and dodges each time it thinks.
That works pretty nicely for a basic model, where each individual agent isn’t really scrutinized. With the current setup, that ignorance was achieved by having a bunch of them everywhere, so that it is really difficult to follow what any one agent was doing. One quirk of this system is that it is really hard to follow behind a given agent, which is basically what the player needs to do in order to kill an agent. This again was remedied by having a bunch of them; if you can’t follow one, just try following another for a bit!
Obviously this issue really bears it’s head when you want to do a one on one duel, because the player will never really be able to keep up with the agent. In playtests of this scenario, the eventual case is that the player is trying to turn around fast enough to get a shot off on the AI, but the AI is trying to get behind the player, causing them to just spin around each other. Not fun.
So, what does FSM do to solve this? A few things. First, it gives me a more extensible system for switching between each strategy. In the current system, it would take a lot of work to get something like waypoint following to happen. With FSM, I just create a new state that has the functionality inside of it, and modify an existing state to transfer to that state. Easy.
Second, FSM changes the agent from doing everything each time to just one, making the agent much more one dimensional. This may seem like a downside, but a one dimensional agent is much more predictable for the player, making it easier (read: feasible) for the player to outmaneuver the agent.
Third, FSM reduces the complexity of the AI itself. Currently the AI class is a mess of variables and obscure parameters, as well as a massive thought function, which is barely extensible to say the least. With FSM, I only call the appropriate base class function inside of AI, and let the state itself handle what actually happens. Easy.
That’s a bunch of reasons for why I should use FSM, but how do I do it? Well, I start out with a base class State, which is more or less an empty class with a few functions and accessor/modifiers. State itself is never really made, just used as a wrapper for the AI class to use all of the states in a way where it doesn’t need to know which state is in use.
After I make the State, I make the actual states, such as State_Attack, which inherits from State. In each subclass, I override an Act() function, which is where all of the magic in the state happens. Act decides what to have the AI point towards, which state (if any) to go to, and whether or not to shoot, among other things. Each state can have its own private members along with the ones provided by the base class State, which lets me have a really extensible system for creating behaviour.
And that’s about it really! Any questions?
2 comments