Development of AI Opponents in Mobile Games
An AI opponent in a mobile game balances between "challenging enough to stay engaging" and "predictable enough that the player feels progress." An opponent that always wins kills motivation in five minutes. One that always loses kills it in ten.
Hierarchical State Machines vs Behaviour Trees
For most mobile games, the choice comes down to two architectures.
Finite State Machines (FSM) are simple, predictable, and easy to debug. Enemy in Patrol state → sees player → transitions to Chase → loses sight → enters Search → back to Patrol. Implementable in hours. Problem: as logic grows complex, the state graph explodes and transition conditions begin to overlap.
Behaviour Trees (BT) are hierarchical structures built from Selector, Sequence, Condition, and Action nodes. Scale better, are easier for designers to read, and support interruptions. Most AAA games use BTs, and mobile games with non-trivial combat should too.
Unity lacks built-in BT support, but open libraries exist—Fluid Behaviour Tree and NodeCanvas (paid but comprehensive). Godot has the Beehave plugin. A minimal BT implementation:
// Unity: simplified Sequence node
public class SequenceNode : BehaviourNode {
private List<BehaviourNode> children;
private int currentIndex = 0;
public override NodeStatus Tick(AIContext context) {
while (currentIndex < children.Count) {
var status = children[currentIndex].Tick(context);
if (status == NodeStatus.Running) return NodeStatus.Running;
if (status == NodeStatus.Failure) {
currentIndex = 0;
return NodeStatus.Failure;
}
currentIndex++;
}
currentIndex = 0;
return NodeStatus.Success;
}
}
Perception: How AI Sees the World
The key question isn't "what does the opponent do" but "what does it know about the world." Without a proper perception system, the BT tree runs on telepathy: enemies know the player's position through walls and react instantly.
Field of View is a visibility cone with angle and range:
bool CanSeePlayer(Transform enemy, Transform player, float viewAngle, float viewDistance) {
Vector3 dirToPlayer = (player.position - enemy.position).normalized;
if (Vector3.Angle(enemy.forward, dirToPlayer) > viewAngle / 2f)
return false; // outside view angle
float dist = Vector3.Distance(enemy.position, player.position);
if (dist > viewDistance) return false;
// Raycast checks for walls between them
return !Physics.Raycast(enemy.position, dirToPlayer, dist,
LayerMask.GetMask("Obstacles"));
}
Hearing involves sound events through a queue: footsteps, gunshots, falling objects. Each event has a radius and falloff. The opponent reacts to events within range, even without seeing the source.
Memory stores the last known player position. If losing sight, move to that position (not current), then transition to Search.
Scaling Difficulty
Fixed difficulty is bad. Dynamic Difficulty Adjustment (DDA) adapts behavior to player performance. Simple tuning parameters:
| Parameter | Easy | Medium | Hard |
|---|---|---|---|
| Player reaction time | 1.2 sec | 0.6 sec | 0.2 sec |
| Field of view | 60° | 90° | 120° |
| Shooting accuracy | 40% | 70% | 90% |
| Patrol time | 8 sec | 5 sec | 3 sec |
Load these from config so designers can tweak without recompiling. DDA automatically shifts parameters based on win rate over the last N sessions.
Mobile Performance
AI ticks shouldn't execute every frame. With 20 enemies on screen:
- BT Tick: every 100–200ms instead of every frame
- Raycast for visibility: use LOD—distant enemies check less often
- Pathfinding: only when target changes, not every tick
Unity's NavMesh works well on mobile, but recalculating paths for all agents in one frame causes spikes. Distribute path recalculation via CoroutineManager or Job System.
Process Overview
Analyze game mechanics and opponent behavior requirements: scenarios and difficulty levels.
Design AI architecture: choose FSM / BT, perception system, memory.
Implement base behaviors, integrate with navigation system (NavMesh).
Tune difficulty parameters, implement DDA.
Playtest and balance: measure player deaths, time-to-kill, win rate per level.
Timeline Estimates
Basic FSM opponent with patrol and chase: 3–5 days. Full system with BT, perception, DDA, and multiple opponent types: 3–6 weeks depending on behavior complexity.







