Basic AI Concepts: State Machines and Decision Trees
Welcome to the foundation of game AI! In this chapter, you'll learn the two most fundamental AI concepts that power intelligent game characters: state machines for behavior control and decision trees for making smart choices.
What You'll Learn
By the end of this chapter, you'll understand:
- How state machines control character behavior
- How decision trees make intelligent choices
- When to use each AI technique
- How to implement both in your games
Understanding State Machines
A state machine is a system that can be in one of several states at any time, and transitions between states based on conditions. Think of it like a character's mood - they can be happy, sad, or angry, and switch between these states based on what happens to them.
Basic State Machine Components
States: The different behaviors or conditions your AI can be in
- Idle (waiting, not doing anything)
- Patrolling (walking around)
- Chasing (following the player)
- Attacking (fighting)
- Fleeing (running away)
Transitions: The conditions that cause the AI to change states
- "If player is nearby, switch from Idle to Chasing"
- "If health is low, switch from Attacking to Fleeing"
- "If player is far away, switch from Chasing to Patrolling"
Simple State Machine Example
Let's create a basic enemy AI that patrols, chases the player, and attacks:
public class EnemyAI : MonoBehaviour
{
public enum AIState
{
Idle,
Patrolling,
Chasing,
Attacking,
Fleeing
}
public AIState currentState = AIState.Idle;
public Transform player;
public float detectionRange = 10f;
public float attackRange = 2f;
public float health = 100f;
void Update()
{
switch (currentState)
{
case AIState.Idle:
IdleBehavior();
break;
case AIState.Patrolling:
PatrollingBehavior();
break;
case AIState.Chasing:
ChasingBehavior();
break;
case AIState.Attacking:
AttackingBehavior();
break;
case AIState.Fleeing:
FleeingBehavior();
break;
}
}
void IdleBehavior()
{
// Check if player is nearby
if (Vector3.Distance(transform.position, player.position) < detectionRange)
{
currentState = AIState.Chasing;
}
// Start patrolling after a few seconds
else if (Time.time > lastStateChange + 3f)
{
currentState = AIState.Patrolling;
}
}
void PatrollingBehavior()
{
// Move to patrol points
MoveToPatrolPoint();
// Check if player is nearby
if (Vector3.Distance(transform.position, player.position) < detectionRange)
{
currentState = AIState.Chasing;
}
}
void ChasingBehavior()
{
// Move towards player
MoveTowardsPlayer();
// Check if close enough to attack
if (Vector3.Distance(transform.position, player.position) < attackRange)
{
currentState = AIState.Attacking;
}
// Check if player is too far away
else if (Vector3.Distance(transform.position, player.position) > detectionRange * 1.5f)
{
currentState = AIState.Patrolling;
}
}
void AttackingBehavior()
{
// Attack the player
AttackPlayer();
// Check if player is still in range
if (Vector3.Distance(transform.position, player.position) > attackRange)
{
currentState = AIState.Chasing;
}
// Check if health is too low
else if (health < 30f)
{
currentState = AIState.Fleeing;
}
}
void FleeingBehavior()
{
// Run away from player
RunAwayFromPlayer();
// Check if health is restored or player is far away
if (health > 50f || Vector3.Distance(transform.position, player.position) > detectionRange * 2f)
{
currentState = AIState.Patrolling;
}
}
}
Understanding Decision Trees
A decision tree is a structure that makes decisions by asking yes/no questions in sequence. It's like a flowchart that guides the AI through a series of choices to reach the best decision.
Decision Tree Structure
Root Node: The starting point of the decision Internal Nodes: Questions or conditions to check Leaf Nodes: The final decisions or actions Branches: The paths between nodes
Simple Decision Tree Example
Let's create a decision tree for an AI that decides what to do based on the situation:
public class AIDecisionTree : MonoBehaviour
{
public Transform player;
public float health = 100f;
public float distanceToPlayer;
public bool hasWeapon = true;
public bool isLowOnAmmo = false;
public enum Decision
{
Attack,
Retreat,
FindAmmo,
Patrol,
Hide
}
public Decision MakeDecision()
{
// Root question: Is the player nearby?
if (distanceToPlayer < 10f)
{
// Player is nearby - check health
if (health < 30f)
{
// Low health - retreat
return Decision.Retreat;
}
else
{
// Good health - check weapon status
if (hasWeapon && !isLowOnAmmo)
{
// Has weapon and ammo - attack
return Decision.Attack;
}
else if (isLowOnAmmo)
{
// Low on ammo - find ammo
return Decision.FindAmmo;
}
else
{
// No weapon - hide
return Decision.Hide;
}
}
}
else
{
// Player is far away - patrol
return Decision.Patrol;
}
}
}
When to Use Each Technique
Use State Machines When:
- You need clear, distinct behaviors
- Behavior changes are event-driven
- You want predictable AI patterns
- You need to debug AI behavior easily
Examples: Enemy AI, NPC behavior, game mode switching
Use Decision Trees When:
- You need complex decision-making
- Decisions depend on multiple factors
- You want flexible, data-driven AI
- You need to balance multiple priorities
Examples: Strategy game AI, resource management, dialogue choices
Combining State Machines and Decision Trees
The most powerful AI systems combine both techniques:
public class AdvancedAI : MonoBehaviour
{
public enum AIState
{
Idle,
Patrolling,
Chasing,
Attacking,
Fleeing
}
public AIState currentState = AIState.Idle;
private AIDecisionTree decisionTree;
void Update()
{
// Use decision tree to determine what state to be in
AIState desiredState = decisionTree.DecideState();
// Use state machine to execute the behavior
if (desiredState != currentState)
{
currentState = desiredState;
}
// Execute current state behavior
ExecuteStateBehavior();
}
}
Pro Tips for AI Development
State Machine Best Practices
- Keep states simple and focused
- Use clear, descriptive state names
- Avoid too many states (5-7 is usually enough)
- Always have a default state
- Test state transitions thoroughly
Decision Tree Best Practices
- Start with the most important decisions
- Keep questions simple and clear
- Avoid overly complex trees
- Use data to drive decisions
- Test edge cases and unusual situations
Common Mistakes to Avoid
- Don't make states too complex
- Don't create decision trees that are too deep
- Don't forget to handle edge cases
- Don't make AI too predictable or too random
- Don't ignore performance implications
Mini Challenge: Create Your Own AI
Try creating a simple AI character that:
- Patrols when the player is far away
- Chases when the player is nearby
- Attacks when close enough
- Flees when health is low
Use a state machine for the behavior and a decision tree for the state transitions.
Troubleshooting Common Issues
AI Gets Stuck in One State
- Check your transition conditions
- Make sure conditions can actually be met
- Add debug logging to see what's happening
AI Makes Poor Decisions
- Review your decision tree logic
- Test with different scenarios
- Consider adding more decision factors
AI Performance Issues
- Limit the frequency of decision-making
- Use simple conditions when possible
- Consider using coroutines for complex AI
What's Next?
Now that you understand the basics of state machines and decision trees, you're ready to learn about pathfinding - how AI characters navigate through your game world. In the next chapter, you'll learn about the A* algorithm and how to implement navigation systems.
Resources
Community Support
- Discord Server: Get help with AI implementation
- GitHub Repository: Share your AI code
- AI Game Development Forums: Learn from other developers
- Course Discussion: Share your progress and get feedback
Ready to learn how AI characters navigate your game world? Continue to [Chapter 3: Pathfinding: A Algorithm and Navigation](/guides/ai-in-game-development/pathfinding-astar-algorithm-navigation) and discover how to create intelligent movement systems.*