270 likes | 516 Views
Game AI Finite State Machine. Introduction (1/2). Finite State Machine (FSM) is the Most Commonly used Game AI Technology Today Simple Efficient Easily extensible Powerful enough to handle a wide variety of situations Theory (Simplified) A set states, S An input vocabulary, I
E N D
Game AI Finite State Machine
Introduction (1/2) • Finite State Machine (FSM) is the Most Commonly used Game AI Technology Today • Simple • Efficient • Easily extensible • Powerful enough to handle a wide variety of situations • Theory (Simplified) • A set states, S • An input vocabulary, I • Transition function, T(s, i) • Map a state and an input to another state
Introduction (2/2) • Practical Use • State • Behavior • Transition • Across states • Conditions • It’s all about driving behavior • Flow-chart Diagram • UML State Chart • Arrow • Transition • Rectangle • State
An Example of FSM As a Diagram Monster in sight Gather Treasure Flee No monster Monster dead Cornered Fight
FSM for Games • Character AI • “Decision-Action” Model • Behavior • Mental State • Transition • Players’ action • The other characters’ actions • Some features in the game world
Implement FSM • Code-based FSM • Simple Code One Up • Straightforward • Most common • Macro-assisted FSM Language • Data-Driven FSM • FSM Script Language
Coding an FSM – Code Example 1 void RunLogic(int *state) { switch(*state) { case 0: // Wander Wander(); if (SeeEnemy()) *state = 1; if (Dead()) *state = 2; break; case 1: // Attack Attack(); *state = 0; if (Dead()) *state = 2; break; case 2: // Dead SlowlyRot(); break; } }
Coding an FSM – Code Example 2 void RunLogic(FSM *fsm) { // Do action based on the state and determine next input input = 0; switch(fsm->GetStateID()) { case 0: // Wander Wander(); if (SeeEnemy()) input = SEE_ENEMY; if (Dead()) input = DEAD; break; case 1: // Attack Attack(); input = WANDER; if (Dead()) input = DEAD; break; case 2: // Dead SlowlyRot(); break; } // DO state transition based on computed input fsm->StateTransition(input); }
Mealy & Moore Machines • Mealy Machine • A Mealy machine is an FSM whose actions are performed on transitions • Moore Machine • A Moore machine’s actions reside in states • More intuitive for game developers
FSM Language Use Macros • Coding a State Machine Directly Causes Lack of Structure • Going complex when FSM at their largest • Use Macro • Beneficial Properties • Structure • Readability • Debugging • Simplicity
FSM Language Use Macros – An Example #define BeginStateMachine … #define State(a) … … bool MyStateMachine::States(StateMachineEvent event, int state) { BeginStateMachine State(0) OnUpdate Wander(); if (SeeEnemy()) SetState(1); if (Dead()) SetState(2); State(1) OnUpdate Attack(); SetState(0); if (Dead()) SetState(2); State(2); OnUpdate RotSlowly(); EndStateMachine }
Data-Driven FSM • Scripting Language • Text-based script file • Transformed into • C++ • Integrated into source code • Bytecode • Interpreted by the game • Authoring • Compiler • AI editing tool • Game • FSM script engine • FSM interface
Data-Driven FSM Diagram Authoring Games FSMs FSM Script Engine bytecode Compiler Artist, Designers, & Developers AI Editing Tool FSM Interface Condition & Action Code Game Engine Condition & Action Vocabulary
AI Editing Tool for FSM • Pure Text • Syntax ? • Visual Graph with Text • Used by Designers, Artists, or Developers • Non-programmers • Conditions & Action Vocabulary • SeeEnemy • CloseToEnemy • Attack • …
FSM Interface • Facilitating the Binding between Vocabulary and Game World • Glue Layer that Implements the Condition & Action Vocabulary in the Game World • Native Conditions • SeeEnemy(), CloseToEnemy() • Action Library • Attack(…)
FSM Script Language Benefits • Accelerated Productivity • Contributions from Artists & Designers • Ease of Use • Extensibility
Processing Models for FSMs • Processing the FSMs • Evaluate the transition conditions for current state • Perform any associated actions • When and How ? • Depend on the exact need of games • Three Common FSM Processing Models • Polling • Event-driven • Multithread
Polling Processing Model • Processing Each FSM at Regular Time Intervals • Tied to game frame rate • Or some desired FSM update frequency • Limit one state transition in a cycle • Give a FSM a time-bound • Pros • Straightforward • Easy to implement • Easy to debug • Cons • Inefficiency • Some transition are not necessary to check every time • Careful Design of Your FSM
Event-driven Processing Model • Designed to Prevent from Wasted FSM Processing • An FSM is Only Processed When It’s relevant • Implementation • A Publish-subscribe messaging system (Observer pattern) • Allows the engine to send events to individual FSMs • An FSM subscribes only to the events that have the potential to change the current state • When an event is generated, the FSMs subscribed to that events are all processed • “As-needed” Approach • Should be much more efficient than polling ? • Tricky Balance for Fine-grained or Coarse-grained Events
Multithread Processing Model • Both Polling & Event-Driven are Serially Processed • Multithread Processing Model • Each FSM is assigned to its own thread for processing • Game engine is running in another separate thread • All FSM processing is effectively concurrent and continuous • Communication between threads must be thread-safe • Using standard locking & synchronization mechanisms • Pros • FSM as an autonomous agent who can constantly and independently examine and react to his environment • Cons • Overhead when many simultaneous characters active • Multithreaded programming is difficult
Interfacing with Game Engine (1/2) • FSMs Encapsulate Complex Behavior Logic • Decision, condition, action, … • Game Engine Does Corresponding • Character animation, movements, sounds, … • The Interface : • Code each action as a function • Need recompile if any code is changed • ie., FleeWolf() • Callbacks • Function pointers • ie., actionFunction[fleeWolf]() • Container method • actionFunctions->FleeWolf(); • DLL
Interfacing with Game Engine (2/2) class AArmyUnit : public FnCharacter { … void DoAttack(…); } AArmyUnit *army; army->Object(…); army->MoveForward(dist, …); … army->DoAttack(…); • Take TheFly3D as Example:
FSM Efficiency & Optimization • Two Categories : • Time spent • Computational cost • Scheduled Processing • Priority for each FSM • Different update frequency • Load Balancing Scheme • Collecting statistics of past performance & extrapolating • Time-bound for Each FSM • Do careful design • At the design level • Level-of-detail FSMs
Level-Of-Detail FSMs • Simplify the FSM When the Player Won’t Notice the Differences • Outside the player’s perceptual range • Just like the LOD technique used in 3D game engine • Three design Keys : • Decide how many LOD levels • How much development time available ? • The approximation extent • LOD selection policy • The distance between the NPC with the player ? • If the NPC can “see” the player ? • Be careful the problem of “visible discontinuous behavior” • What kind of approximations • Cheaper and less accurate solution
Extending the Basic FSM • Extending States • Begin-end block • Stacks & FSMs • Stack-based “history” of FSMs • “Remember” the sequence of states passed through • “Retrace” its steps at will • Hierarchical FSM • Polymorphic FSMs • Fuzzy State Machine • Combined with fuzzy logic BeginDoAction(); DoActions(); EndDoAction();
A Hierarchical FSM Example Monster in sight Gather Treasure No monster Flee Monster dead Fight Cornered Find Treasure Active FSM Go To Treasure Gather Treasure Find Treasure Live Stack Take Treasure
Another Hierarchical FSM Example Patrol Done Done Noise Investigate Saw Enemy Attack Saw Enemy Patrol Go to A Look for Intruders Go to A Look for Intruders noise noise Report Noise Go Over To Noise Look for Intruders False Alerm! Investigate